Skip to content

feat(ems): EMS controller gets its own device identity and tailored dashboard#96

Merged
dewet22 merged 1 commit into
mainfrom
feat/ems-aware-dashboard
Jun 1, 2026
Merged

feat(ems): EMS controller gets its own device identity and tailored dashboard#96
dewet22 merged 1 commit into
mainfrom
feat/ems-aware-dashboard

Conversation

@dewet22

@dewet22 dewet22 commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Problem

An EMS config entry was modelled as an inverter throughout: the device was named
"GivEnergy Inverter {serial}" (so its entities slugged givenergy_inverter_…), and
generate_dashboard emitted the full inverter view set (Overview / Energy / Controls),
which renders blank on an EMS — no PV/battery/grid sensors, no inverter controls. The
EMS's genuinely useful entities (scheduling controls) weren't in the generated dashboard
at all. Reported on #52 (confirmed against the reporter's real EMS plant snapshot).

Fix

Model-aware device naming (sensor.py)

The device is now named by kind: "GivEnergy EMS {serial}" for EMS controllers,
"GivEnergy Gateway {serial}" for gateways (future-proofs #95), "GivEnergy Inverter {serial}" for everything else (unchanged). Fresh EMS installs automatically derive
givenergy_ems_… entity ids from this name.

EMS-tailored dashboard (dashboard.py, DASHBOARD_VERSION 4 → 5)

generate_dashboard(…, is_ems=True) emits a two-view set instead of the inverter views:

  • EMS Controls — Flexi EMS Control switch + per-slot start/end times and target SOC
    for charge / discharge / export slots 1–3.
  • Diagnostics — Integration Health card only (coordinator poll-health sensors, which
    do exist for an EMS).

The service handler passes is_ems = coordinator.data.ems is not None. Inverter
dashboards are completely unchanged.

Realignment for existing installs (§5 in the plan)

We deliberately do not auto-mutate the entity registry — the registry can't
distinguish a user-customised id from one we renamed, so auto-migration would either
clobber customisations or miss entity renames (not just device renames). Instead the
realignment path is HA's native "Recreate entity IDs" device action, which handles
both. A self-clearing repair issue (keyed on the dashboard version) prompts affected
users: run "Recreate entity IDs" on the EMS device, then regenerate the dashboard;
the recorder preserves history across the rename.

Alignment with modbus#106

_device_kind(model) is the single source-of-kind seam that modbus#106's typed-device
enumeration will feed — when that lands, only that helper changes, not the naming,
dashboard branching, or prompt code. givenergy_ems_ is the stable end-state #106 keeps,
so existing users migrate once here and never again.

Notes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added EMS controller dashboard with dedicated controls and diagnostics views
    • Device names now accurately reflect device type (Inverter/EMS/Gateway)
  • Bug Fixes

    • Added detection and warning for outdated entity IDs from legacy naming scheme
  • Documentation

    • Added notification guiding users on entity ID realignment for EMS controllers

… dashboard

An EMS config entry was modelled as an inverter: the device was named "GivEnergy
Inverter {serial}" (so its entities slugged givenergy_inverter_…), and the
generated dashboard emitted inverter views that render blank on an EMS — no
PV/battery/grid sensors, no inverter controls. Reported on #52.

- Device naming is now model-aware (sensor._device_kind): EMS → "GivEnergy EMS
  {serial}", Gateway → "GivEnergy Gateway {serial}" (future-proofs #95); all
  actual inverters unchanged. Fresh EMS installs derive givenergy_ems_ entity ids.
- generate_dashboard gains is_ems: an EMS plant gets a tailored pair — an EMS
  Controls view (slot times + target SOC + Flexi switch) and a health-only
  Diagnostics view — with givenergy_ems_ references. Inverter dashboards unchanged.
- Existing EMS installs realign via HA's native "Recreate entity IDs" action — we
  don't auto-mutate the registry (it can't distinguish a user-customised id from a
  renamed one). A self-clearing repair issue prompts recreate + dashboard
  regenerate; the recorder preserves history across the rename.
- DASHBOARD_VERSION 4 → 5.

Forward step toward the typed-device model (modbus#106): _device_kind is the single
source-of-kind seam #106 will feed, and givenergy_ems_ is the stable end-state #106
keeps — so users migrate once, here.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5f0b65f6-d53d-413c-b766-f3815790a286

📥 Commits

Reviewing files that changed from the base of the PR and between 736cd12 and 7a35a5b.

📒 Files selected for processing (8)
  • custom_components/givenergy_local/__init__.py
  • custom_components/givenergy_local/dashboard.py
  • custom_components/givenergy_local/sensor.py
  • custom_components/givenergy_local/strings.json
  • custom_components/givenergy_local/translations/en.json
  • tests/test_dashboard.py
  • tests/test_ems.py
  • tests/test_sensor.py

📝 Walkthrough

Walkthrough

This PR adds EMS (Energy Management System) support to the GivEnergy Home Assistant integration. The changes introduce device kind classification to differentiate between Inverter, EMS, and Gateway devices, generate EMS-specific Lovelace dashboards, detect legacy entity ID naming during setup, and guide users through migration with repair issues. The dashboard version is bumped to 5 with refactored integration health reporting and comprehensive test coverage.

Changes

EMS Integration Support

Layer / File(s) Summary
Device Kind Classification & Device Naming
custom_components/givenergy_local/sensor.py, tests/test_sensor.py
_device_kind(model) maps device models to broader kinds (Inverter, EMS, Gateway) for use in dynamic device naming. GivEnergyInverterSensor now constructs device names using the computed kind, replacing the hardcoded "GivEnergy Inverter" prefix.
Dashboard Version, Health Card Refactoring, EMS Parameter
custom_components/givenergy_local/dashboard.py, tests/test_dashboard.py
Dashboard version incremented to 5. _integration_health_card(inv, kind="inverter") extracted as a reusable helper supporting both inverter and EMS diagnostics. generate_dashboard signature updated with is_ems keyword flag to conditionally route to EMS or inverter dashboard variants. Version assertion in tests updated to 5.
EMS Dashboard Views & Test Coverage
custom_components/givenergy_local/dashboard.py, tests/test_dashboard.py
EMS-specific dashboard builders added: _ems_slot_card for charge/discharge/export slot controls, _ems_controls_view for EMS control page, and _ems_diagnostics_view reusing the health card helper. Four new tests validate EMS view selection, entity ID naming conventions, inverter control exclusion, and full slot coverage.
Entity ID Realignment & Repair Issue
custom_components/givenergy_local/__init__.py, custom_components/givenergy_local/strings.json, custom_components/givenergy_local/translations/en.json
During async_setup_entry, entity registry is checked for legacy givenergy_inverter_ prefixed IDs when EMS is present. Non-fixable repair issue ems_entity_ids_outdated is created or deleted based on stale ID detection to guide users through entity recreation and dashboard regeneration.
EMS Integration & Test Setup
custom_components/givenergy_local/__init__.py, tests/test_ems.py
Dashboard generation now passes is_ems flag computed from coordinator.data.ems to enable variant selection. EMS test fixture updated to accept controller context and set mock_inverter.model = Model.EMS. Three new integration tests verify EMS device naming, confirm repair issue behavior on fresh installs vs. stale entity detection.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • dewet22/givenergy-hass#71: Both PRs modify the Integration Health dashboard card in dashboard.py, with the main refactoring extracting the health card into a reusable helper supporting device kinds.
  • dewet22/givenergy-hass#79: Both PRs bump DASHBOARD_VERSION and modify generate_dashboard to alter Lovelace view rendering and composition.

Poem

🐰 A new kind hops into the garden,

EMS gardens join Inverter rows—
Device names bloom with their true colors,
Legacy dashboards shed their skins,
Repair issues guide the way home. 🌱

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 56.25% 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 clearly and specifically describes the main changes: EMS controller device identity updates and tailored dashboard generation.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ems-aware-dashboard

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 support for EMS (Energy Management System) plant controllers by giving them their own device identity and entity ID prefix (givenergy_ems_ instead of givenergy_inverter_). It adds a tailored EMS dashboard featuring scheduling controls and integration health, raises a repair issue prompting users to recreate entity IDs for existing installations, and updates corresponding tests and translations. The review feedback suggests adding a defensive None check on coordinator.data in __init__.py to prevent potential AttributeErrors if the coordinator's data has not yet been populated.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread custom_components/givenergy_local/__init__.py
@dewet22-codex

Copy link
Copy Markdown
Collaborator

I’ve started reviewing this PR.

@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. I ran uv run pytest -q (172 passed), uv run pytest tests/test_ems.py tests/test_dashboard.py -q (30 passed), uv lock --check, and targeted ruff on the changed files; GitHub checks are green apart from CodeRabbit still being in progress at review time.

@dewet22 dewet22 merged commit ec3d288 into main Jun 1, 2026
8 of 9 checks passed
@dewet22 dewet22 deleted the feat/ems-aware-dashboard branch June 1, 2026 22:38
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