Part 7 of 7 · Home Assistant Energy Build

The dashboard

The human interface to everything built so far: a five-tab "My Energy" dashboard covering battery, live power, hot water and the Octopus tariff — shown here with the complete Lovelace config, genericised.

A system that automates itself still needs to be readable at a glance — both to trust it and to catch when something is off. The "My Energy" dashboard is the human interface to everything built in the previous six parts. It is a five-tab (five-view) Lovelace dashboard using the modern sections layout, set as the default view on the phone so a single tap shows the whole state of the house.

What the dashboard is for

The design brief is narrow on purpose: show state of charge, show where power is flowing right now, show today's energy and money, and expose just the handful of controls that arm the overnight routines. Everything else lives in the automations. The dashboard is a window, not a cockpit — with a few clearly-labelled switches. The five tabs are:

TabWhat it shows
HomeBattery gauge, live power flow, quick controls, today's totals and costs, 24-hour history.
Timed ChargeThe overnight grid-charge slot and AC charge rate.
Discharge ScheduleThe discharge window that locks the battery overnight.
Eddi & Hot WaterTonight's plan, Eddi mode, a manual boost button and energy stats.
OctopusLive tariff status, costs, cheap-rate window, greenness forecast and Octoplus.

The Home tab

The Home tab is the one that opens by default. Its header is a plain markdown title, ✨ My Energy, and it carries three badges across the top for the numbers worth seeing without scrolling: battery state of charge, a battery discharge-status sensor, and a Cheap Rate badge wired to the Octopus off-peak binary sensor.

Below the badges the sections run top to bottom:

The power-flow card is the centrepiece, and the one card with a real gotcha worth isolating:

type: custom:power-flow-card-plus
title: Live Power Flow
entities:
  battery:
    entity: sensor.givtcp_gwXXXXXXXX_battery_power
    state_of_charge: sensor.givtcp_gwXXXXXXXX_soc
  grid:
    entity: sensor.givtcp_gwXXXXXXXX_grid_power
    invert_state: true      # GivTCP sign is inverted vs the card
  solar:
    entity: sensor.givtcp_gwXXXXXXXX_pv_power
  home:
    entity: sensor.givtcp_gwXXXXXXXX_load_power

Timed Charge & Discharge tabs

Two tabs expose the raw GivTCP schedule entities behind the overnight routine. They exist so the schedule can be inspected and, if needed, nudged by hand — but the day-to-day management is the automations' job.

The Timed Charge tab is an entities card for the slot-1 charge schedule: schedule enable switch, start and end times, target SOC, AC charge rate, and battery mode. A markdown note spells out that it is managed automatically — the battery charges 01:00–02:00 at 48% (5.7kW) to protect the 32A breaker — and warns that externally-made manual changes will be reverted by the Settings Guardian from Part 6.

Why the discharge tab matters — The Discharge Schedule tab controls the window in which the battery is allowed to discharge. Outside that window the battery is locked — which is what stops it powering the Eddi during the overnight boost. The schedule is set automatically at 20:59/21:00 and disabled at 06:30, and the 🔒 badge on Home reflects whether the battery is currently locked.

The Eddi & Hot Water tab

This tab is where a human interacts with the hot-water side. It has four sections:

The manual boost is the only place the dashboard does more than toggle a helper — it fires a script, via a button card:

type: button
entity: script.manual_eddi_boost
name: Boost Now
icon: mdi:water-boiler-alert
tap_action:
  action: perform-action
  perform_action: script.turn_on
  target:
    entity_id: script.manual_eddi_boost
show_state: false

The Octopus tab

The richest tab, and purely informational — nothing here writes to a device. It turns the Octopus integration from Part 5 into something glanceable:

The status banner is the neatest bit — a self-contained template card that colours itself by tariff period:

type: markdown
content: >-
  {% set off_peak =
  is_state('binary_sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_off_peak',
  'on') %} {% set rate =
  (states('sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_current_rate')
  | float(0) * 100) | round(1) %} {% if off_peak %}

  ## 🟢 CHEAP RATE — {{ rate }}p/kWh

  Cheap window active. Run heavy loads now — dishwasher, washing
  machine, anything deferrable. {% else %}

  ## 🔴 PEAK RATE — {{ rate }}p/kWh

  Peak pricing. Defer non-urgent loads if possible. {% endif %}

The read-only Solar dashboard

The second user created back in Part 2 — the non-admin "Solar" account for a colleague — gets a duplicate of the Home view with the control cards removed. It keeps the SOC gauge, power flow, totals and history, but drops Quick Controls and Battery Control, so a guest can watch generation and battery state without being able to change charge schedules or operating modes.

Design note — Home Assistant doesn't enforce per-card permissions, so "read-only" here means a purpose-built view that simply never surfaces a writable control, shown to a non-admin account. It is the account model and the dashboard design working together — set up early in Part 2 precisely so it slots in cleanly here.

The full dashboard config

Here is the complete Lovelace YAML for all five tabs, exactly as it runs — with device serials, meter numbers and the account ID replaced by placeholders. Everything else (entity naming patterns, card options, the template cards) is verbatim, so it reads as a working reference for how a dashboard like this is wired.

Placeholders — gwXXXXXXXX is the GivEnergy Gateway serial, XXXXXXXX the Eddi serial, xxxxxxxxxx the Octopus electricity meter serial, XXXXXXXXXXXXX the import/export MPANs, and a_xxxxxxxx the Octopus account ID. Swap in your own values.

views:
  - type: sections
    sections:
      - type: grid
        cards:
          - type: heading
            heading: Battery
            heading_style: title
            icon: mdi:battery
          - type: gauge
            entity: sensor.givtcp_gwXXXXXXXX_soc
            name: Battery
            needle: true
            severity:
              green: 50
              yellow: 20
              red: 0
      - type: grid
        cards:
          - type: heading
            heading: Live Power
            heading_style: title
            icon: mdi:lightning-bolt
          - type: custom:power-flow-card-plus
            title: Live Power Flow
            entities:
              battery:
                entity: sensor.givtcp_gwXXXXXXXX_battery_power
                state_of_charge: sensor.givtcp_gwXXXXXXXX_soc
                color_circle: true
              grid:
                entity: sensor.givtcp_gwXXXXXXXX_grid_power
                invert_state: true
              solar:
                entity: sensor.givtcp_gwXXXXXXXX_pv_power
              home:
                entity: sensor.givtcp_gwXXXXXXXX_load_power
                override_state: true
                use_metadata: false
            clickable_entities: true
            display_zero_lines:
              mode: show
              transparency: 50
              grey_color:
                - 189
                - 189
                - 189
            use_new_flow_rate_model: true
            w_decimals: 0
            kw_decimals: 1
            min_flow_rate: 0.75
            max_flow_rate: 6
            watt_threshold: 1000
      - type: grid
        cards:
          - type: heading
            heading: Quick Controls
            heading_style: title
            icon: mdi:toggle-switch
          - type: tile
            entity: select.eddi_XXXXXXXX_myenergi_eddi_XXXXXXXX_operating_mode
            name: Eddi Mode
            color: green
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.eddi_XXXXXXXX_myenergi_eddi_XXXXXXXX_internal_load_ct1
            name: Eddi Power
            color: deep-orange
            vertical: true
            features_position: bottom
          - type: markdown
            content: >-
              **Stopped** = Eddi off, max solar export at 12p. **Normal** = Eddi
              diverts surplus solar to hot water. Set to Normal during the day
              if you want free hot water from solar.
      - type: grid
        cards:
          - type: heading
            heading: Battery Control
            heading_style: title
            icon: mdi:battery-charging
          - type: tile
            entity: select.givtcp_gwXXXXXXXX_mode
            name: Battery Mode
            color: cyan
            vertical: true
            features_position: bottom
          - type: tile
            entity: select.givtcp_gwXXXXXXXX_temp_pause_charge
            name: Pause Charge
            color: amber
            vertical: true
            features_position: bottom
          - type: tile
            entity: select.givtcp_gwXXXXXXXX_temp_pause_discharge
            name: Pause Discharge
            color: amber
            vertical: true
            features_position: bottom
          - type: markdown
            content: >-
              **Eco** = normal operation, battery charges/discharges
              automatically. **Eco (Paused)** = battery fully paused. **Timed
              Demand** = force charge from grid now. **Timed Export** = force
              discharge/export now. Pause Charge/Discharge = temporary pause for
              set minutes.
      - type: grid
        cards:
          - type: heading
            heading_style: title
            heading: Today's Totals
            icon: mdi:calculator
          - type: tile
            entity: sensor.givtcp_gwXXXXXXXX_pv_energy_today_kwh
            name: Solar Today
            color: amber
            show_entity_picture: false
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.givtcp_gwXXXXXXXX_import_energy_today_kwh
            name: Grid In
            color: red
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.givtcp_gwXXXXXXXX_export_energy_today_kwh
            name: Grid Out
            color: blue
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.givtcp_gwXXXXXXXX_battery_charge_energy_today_kwh
            name:
              type: entity
            color: green
            vertical: true
            features_position: bottom
      - type: grid
        cards:
          - type: heading
            heading_style: title
            heading: Today's Costs
            icon: mdi:currency-gbp
          - type: tile
            entity: sensor.daily_export_revenue
            name: Export Revenue
            color: green
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.daily_import_cost
            name: Import Cost
            color: red
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.daily_net_position
            name: Net Position
            color: blue
            vertical: true
            features_position: bottom
          - type: markdown
            content: >-
              Export at 12p/kWh. Import estimated at 9p/kWh (most import is
              overnight cheap rate). Positive net = earning money.
      - type: grid
        cards:
          - type: heading
            heading: History
            heading_style: title
            icon: mdi:book
          - type: history-graph
            entities:
              - entity: sun.sun
              - entity: sensor.givtcp_gwXXXXXXXX_soc
            title: Battery SOC - Last 24 Hours
          - type: history-graph
            entities:
              - entity: sun.sun
              - entity: sensor.givtcp_gwXXXXXXXX_pv_power
              - entity: sensor.givtcp_gwXXXXXXXX_battery_power
              - entity: sensor.givtcp_gwXXXXXXXX_grid_power
            title: Power Flows - Last 24 Hours
    header:
      card:
        type: markdown
        text_only: true
        content: "# ✨ My Energy"
    badges:
      - type: entity
        show_name: false
        show_state: true
        show_icon: true
        entity: sensor.givtcp_gwXXXXXXXX_soc
      - type: entity
        show_name: true
        show_state: true
        show_icon: true
        entity: sensor.battery_discharge_status
        name: Battery
      - type: entity
        show_name: true
        show_state: true
        show_icon: true
        entity: >-
          binary_sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_off_peak
        name: Cheap Rate
    max_columns: 4
    title: Home
    cards: []
  - type: sections
    max_columns: 4
    title: Timed Charge
    path: timed-charge
    sections:
      - type: grid
        cards:
          - type: entities
            entities:
              - entity: switch.givtcp_gwXXXXXXXX_enable_charge_schedule
                name: Schedule Enabled
              - entity: select.givtcp_gwXXXXXXXX_charge_start_time_slot_1
                name: Charge Start Slot 1
              - entity: select.givtcp_gwXXXXXXXX_charge_end_time_slot_1
                name: Charge End Slot 1
              - entity: number.givtcp_gwXXXXXXXX_charge_target_soc_1
                name: "Target SOC #1 %"
              - entity: number.givtcp_gwXXXXXXXX_battery_charge_rate_ac
                name: AC Charge Rate %
              - entity: select.givtcp_gwXXXXXXXX_mode
                name: Battery Mode
          - type: markdown
            content: >-
              Managed automatically by the overnight automations. Battery
              charges 01:00–02:00 at 48% (5.7kW) to protect the 32A breaker.
              Manual changes here will be reverted by the Settings Guardian if
              made externally.
    header:
      card:
        type: markdown
        text_only: true
        content: "# Timed Charge"
  - type: sections
    max_columns: 4
    title: Discharge Schedule
    path: discharge-schedule
    sections:
      - type: grid
        cards:
          - type: entities
            entities:
              - entity: switch.givtcp_gwXXXXXXXX_enable_discharge_schedule
                name: Discharge Schedule Enabled
              - entity: select.givtcp_gwXXXXXXXX_discharge_start_time_slot_1
                name: Discharge Allowed From
              - entity: select.givtcp_gwXXXXXXXX_discharge_end_time_slot_1
                name: Discharge Must Stop By
              - entity: number.givtcp_gwXXXXXXXX_battery_discharge_rate
                name: Discharge Rate %
            title: Discharge Schedule
          - type: markdown
            content: >-
              **How it works:** When enabled, the battery can only discharge
              between **Allowed From** and **Must Stop By**. Outside this window
              the battery is locked — preventing it from powering the Eddi
              during the overnight boost. The schedule is set automatically at
              20:59/21:00 and disabled at 06:30. The 🔒 badge on the Home tab
              shows whether the battery is currently locked.
    header:
      card:
        type: markdown
        text_only: true
        content: "# Discharge Schedule"
  - type: sections
    max_columns: 4
    title: Eddi & Hot Water
    path: eddi-status
    sections:
      - type: grid
        cards:
          - type: heading
            heading: Tonight's Plan
            heading_style: title
          - type: tile
            entity: input_boolean.charge_battery_tonight
          - type: tile
            entity: input_boolean.boost_hot_water_tonight
          - type: tile
            entity: input_datetime.eddi_boost_start
          - type: tile
            entity: input_number.eddi_boost_duration
          - type: markdown
            content: >-
              Both auto-enable each evening (battery at 21:00, Eddi at 20:59).
              Toggle off to skip tonight. Boost start and duration are
              auto-adjusted when both are enabled to avoid overlap.
      - type: grid
        cards:
          - type: heading
            heading: Eddi Control
            heading_style: title
          - type: tile
            entity: select.eddi_XXXXXXXX_myenergi_eddi_XXXXXXXX_operating_mode
            name: Eddi Mode
            color: green
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.eddi_XXXXXXXX_myenergi_eddi_XXXXXXXX_active_heater
            name: Active Heater
            color: deep-orange
            vertical: true
            features_position: bottom
      - type: grid
        cards:
          - type: heading
            heading: Manual Boost
            heading_style: title
            icon: mdi:water-boiler-alert
          - type: tile
            entity: input_number.manual_boost_minutes
            name: Boost Duration (mins)
            color: deep-orange
            vertical: true
            features_position: bottom
          - type: button
            entity: script.manual_eddi_boost
            name: Boost Now
            icon: mdi:water-boiler-alert
            tap_action:
              action: perform-action
              perform_action: script.turn_on
              target:
                entity_id: script.manual_eddi_boost
            show_state: false
          - type: markdown
            content: >-
              Set duration then tap Boost Now. Works even if Eddi is Stopped —
              it will switch to Normal automatically before boosting. Battery
              drain protection is active during manual boosts.
      - type: grid
        cards:
          - type: heading
            heading: Energy Stats
            heading_style: title
            icon: mdi:lightning-bolt
          - type: tile
            entity: sensor.eddi_XXXXXXXX_myenergi_eddi_XXXXXXXX_energy_used_today
            name: Hot Water Today
            color: red
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.eddi_XXXXXXXX_myenergi_eddi_XXXXXXXX_energy_consumed_session
            name: Current Session
            color: amber
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.eddi_XXXXXXXX_myenergi_eddi_XXXXXXXX_ct_internal_load_today
            name: Diverted Today
            color: yellow
            vertical: true
            features_position: bottom
    header:
      card:
        type: markdown
        text_only: true
        content: "# Eddi & Hot Water"
  - type: sections
    max_columns: 4
    title: Octopus
    path: octopus
    icon: ""
    sections:
      - type: grid
        cards:
          - type: heading
            heading: Current Status
            heading_style: title
            icon: mdi:flash
          - type: markdown
            content: >-
              {% set off_peak =
              is_state('binary_sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_off_peak',
              'on') %} {% set rate =
              (states('sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_current_rate')
              | float(0) * 100) | round(1) %} {% if off_peak %}

              ## 🟢 CHEAP RATE — {{ rate }}p/kWh


              Cheap window active. Run heavy loads now — dishwasher, washing
              machine, anything deferrable. {% else %}

              ## 🔴 PEAK RATE — {{ rate }}p/kWh


              Peak pricing. Defer non-urgent loads if possible. {% endif %}
      - type: grid
        cards:
          - type: heading
            heading: Live Now
            heading_style: title
            icon: mdi:flash
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_current_accumulative_consumption
            name: Import Today
            color: red
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_current_accumulative_cost
            name: Cost Today
            color: orange
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_current_demand
            name: Drawing Now
            color: yellow
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_current_rate
            name: Current Rate
            color: blue
            vertical: true
            features_position: bottom
          - type: markdown
            content: >-
              **Drawing Now** shows net grid flow. **Negative = exporting** to
              the grid, **positive = importing** from the grid.
      - type: grid
        cards:
          - type: heading
            heading: Cheap Rate Window
            heading_style: title
            icon: mdi:clock-outline
          - type: entities
            entities:
              - entity: >-
                  binary_sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_off_peak
                name: Off-Peak Active Now
              - entity: >-
                  sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_next_rate
                name: Next Rate
          - type: markdown
            content: >-
              **Off-Peak Active** lights up between 00:30 and 06:00 on the Snug
              tariff. **Next Rate** shows the rate that kicks in at the next
              transition.
      - type: grid
        cards:
          - type: heading
            heading: Eddi Cost Tracker
            heading_style: title
            icon: mdi:water-boiler
          - type: tile
            entity: sensor.octopus_energy_cost_tracker_eddi_hot_water_heating
            name: Today
            color: amber
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.octopus_energy_cost_tracker_eddi_hot_water_heating_week
            name: This Week
            color: amber
            vertical: true
            features_position: bottom
          - type: tile
            entity: sensor.octopus_energy_cost_tracker_eddi_hot_water_heating_month
            name: This Month
            color: amber
            vertical: true
            features_position: bottom
          - type: markdown
            content: >-
              Cost of running the Eddi against your actual Octopus rates. Will
              show Unknown until the first boost runs after the tracker was
              configured.
      - type: grid
        cards:
          - type: heading
            heading: Yesterday Actuals
            heading_style: title
            icon: mdi:calendar
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_previous_accumulative_consumption
            name: Import Yesterday
            color: red
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_previous_accumulative_cost
            name: Import Cost
            color: orange
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_export_previous_accumulative_consumption
            name: Export Yesterday
            color: green
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_export_previous_accumulative_cost
            name: Export Credit
            color: green
            vertical: true
            features_position: bottom
          - type: markdown
            content: >-
              These are the bill-accurate smart-meter figures Octopus uses for
              billing. Yesterday's data typically lands by mid-morning.
      - type: grid
        cards:
          - type: heading
            heading: Tariff Info
            heading_style: title
            icon: mdi:information
          - type: entities
            entities:
              - entity: >-
                  sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_current_standing_charge
                name: Standing Charge (Import)
              - entity: >-
                  sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_export_current_rate
                name: Export Rate (Now)
              - entity: >-
                  sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_export_next_rate
                name: Export Rate (Next)
              - entity: >-
                  sensor.octopus_energy_electricity_xxxxxxxxxx_XXXXXXXXXXXXX_export_current_standing_charge
                name: Export Standing Charge
      - type: grid
        cards:
          - type: heading
            heading: Greenness Forecast
            heading_style: title
            icon: mdi:leaf
          - type: custom:octopus-energy-greenness-forecast-card
            currentEntity: sensor.octopus_energy_a_xxxxxxxx_greenness_forecast_current_index
            futureEntity: sensor.octopus_energy_a_xxxxxxxx_greenness_forecast_next_index
            lowLimit: 15
            mediumLimit: 20
            highLimit: 30
            showTimes: true
            showDays: 7
            hour12: false
            indexCase: ucf
          - type: markdown
            content: >-
              Octopus's prediction of how clean the UK grid will be on each
              upcoming night. ⭐ Highlighted nights are the greenest — best time
              to charge if you're flexible about timing rather than just going
              for cheapest.
      - type: grid
        cards:
          - type: heading
            heading: Octoplus
            heading_style: title
            icon: mdi:gift
          - type: conditional
            conditions:
              - condition: state
                entity: >-
                  binary_sensor.octopus_energy_a_xxxxxxxx_octoplus_saving_sessions
                state: "on"
            card:
              type: markdown
              content: |-
                ## ⚡ Saving Session ACTIVE

                Reduce usage now to earn Octoplus points.
          - type: tile
            entity: sensor.octopus_energy_a_xxxxxxxx_octoplus_points
            name: Points
            color: purple
            vertical: true
            features_position: bottom
          - type: tile
            entity: >-
              sensor.octopus_energy_a_xxxxxxxx_wheel_of_fortune_spins_electricity
            name: Wheel Spins
            color: amber
            vertical: true
            features_position: bottom
          - type: tile
            entity: binary_sensor.octopus_energy_a_xxxxxxxx_octoplus_saving_sessions
            name: Saving Session Active
            color: green
            vertical: true
            features_position: bottom
    header:
      card:
        type: markdown
        text_only: true
        content: "# 🐙 Octopus"
    cards: []

That completes the series. The system now runs its whole cheap-rate routine locally: capping charge to a breaker-safe rate, filling the battery and heating the tank overnight on ~7p energy, verifying the cloud-backed devices actually did as they were told, defending against cloud interference, and presenting the whole thing on a single glanceable dashboard — with a read-only view for a second pair of eyes.

Outstanding threads, kept honest: re-basing the dashboard totals onto Octopus meter data (Part 5), and the still-planned Alexa / Echo Show display. The build is a living system, and this log will track it as those land.

A personal home-energy project, shared as-is and not affiliated with any vendor mentioned. The dashboard config is shared as a reference — entity naming patterns are specific to this installation, and serials, meter numbers and the account ID have been replaced with placeholders. Check current vendor docs before reusing any of it.