Home Assistant Batterie-Monitor Komplettlösung

Home Assistant Batterie-Monitor Komplettlösung

Ein modernes Energiemanagement ist ohne präzise Batteriedaten kaum möglich. Viele PV-Speicher liefern jedoch nur grundlegende Informationen, die für Automationen oder detaillierte Analysen oft nicht ausreichen.

Dieser erweiterte Home Assistant Template Sensor schafft Abhilfe: Er berechnet Restlaufzeit, Lade-ETA, erkennt den Status intelligent, filtert Kleinstleistungen unter ±5 Watt und liefert perfekt strukturierte Werte für Dashboards und Automationen.

Ideal für alle, die ihren Batteriespeicher effizient überwachen möchten.

Vorteile

  • Präzise Statuslogik: Standby, Laden, Entladen ab ±5 W
  • Restzeit & ETA: dynamisch berechnet, leer bei Standby
  • Dynamische Icons: abhängig von Ladezustand & Lade-/Entlademodus
  • Attribute für Automationen: status, soc, restzeit, eta, leistung
  • Kompatibel mit Lovelace & Automationen

Template-Sensor – v1.0

template:
  - sensor:
      - name: "Batterie-restzeit"
        unique_id: batterie_restzeit
        state: >
          {% raw %}{% set power = states('sensor.rct_power_storage_battery_power') | float(0) %}
          {% if power | abs <= 5 %}Standby
          {% elif power < -5 %}Lädt
          {% else %}Entlädt
          {% endif %}{% endraw %}
        icon: >
          {% raw %}{% set soc = states('sensor.rct_power_storage_battery_state_of_charge') | float(0) %}
          {% set power = states('sensor.rct_power_storage_battery_power') | float(0) %}
          {% if power < -5 %}
            {% if soc >= 95 %}mdi:battery-charging-100
            {% elif soc >= 85 %}mdi:battery-charging-90
            {% elif soc >= 65 %}mdi:battery-charging-70
            {% elif soc >= 45 %}mdi:battery-charging-50
            {% elif soc >= 25 %}mdi:battery-charging-30
            {% elif soc >= 10 %}mdi:battery-charging-20
            {% else %}mdi:battery-charging-outline
            {% endif %}
          {% elif power > 5 %}
            {% if soc >= 95 %}mdi:battery
            {% elif soc >= 85 %}mdi:battery-90
            {% elif soc >= 65 %}mdi:battery-70
            {% elif soc >= 45 %}mdi:battery-50
            {% elif soc >= 25 %}mdi:battery-30
            {% elif soc >= 10 %}mdi:battery-20
            {% else %}mdi:battery-alert
            {% endif %}
          {% else %}
            {% if soc >= 85 %}mdi:battery
            {% elif soc >= 65 %}mdi:battery-70
            {% elif soc >= 45 %}mdi:battery-50
            {% elif soc >= 25 %}mdi:battery-30
            {% elif soc >= 10 %}mdi:battery-20
            {% else %}mdi:battery-outline
            {% endif %}{% endraw %}
        attributes:
          status: >
            {% raw %}{% set p = states('sensor.rct_power_storage_battery_power') | float(0) %}
            {% if p | abs <= 5 %}Standby
            {% elif p < -5 %}Lädt
            {% else %}Entlädt
            {% endif %}{% endraw %}
          soc: >
            {% raw %}{{ states('sensor.rct_power_storage_battery_state_of_charge') | float(0) | round(1) }} %{% endraw %}
          restzeit: >
            {% raw %}{% set p = states('sensor.rct_power_storage_battery_power') | float(0) %}
            {% if p | abs <= 5 %}{{ "" }}
            {% else %}
              {% set size = 7.5 %}
              {% set soc = states('sensor.rct_power_storage_battery_state_of_charge') | float(0) %}
              {% set target = states('sensor.rct_power_storage_battery_state_of_charge_target') | float(100) %}
              {% if p < 0 %}
                {% set e_diff = (target - soc) / 100 * size %}
              {% else %}
                {% set e_diff = (soc - 7) / 100 * size %}
              {% endif %}
              {% set hours = e_diff / (p | abs / 1000) %}
              {% if hours > 0 %}
                {% set mins = (hours * 60) | round(0) %}
                {% set h = mins // 60 %}
                {% set m = mins % 60 %}
                {% if h > 0 %}{{ h }}h {{ "%02d"|format(m) }}min{% else %}{{ m }}min{% endif %}
              {% else %}Unbekannt{% endif %}
            {% endif %}{% endraw %}
          eta: >
            {% raw %}{% set p = states('sensor.rct_power_storage_battery_power') | float(0) %}
            {% if p | abs <= 5 %}{{ "" }}
            {% else %}
              {% set size = 7.5 %}
              {% set soc = states('sensor.rct_power_storage_battery_state_of_charge') | float(0) %}
              {% set target = states('sensor.rct_power_storage_battery_state_of_charge_target') | float(100) %}
              {% if p < 0 %}
                {% set e_diff = (target - soc) / 100 * size %}
              {% else %}
                {% set e_diff = (soc - 7) / 100 * size %}
              {% endif %}
              {% set hours = e_diff / (p | abs / 1000) %}
              {% if hours > 0 %}
                {{ (now() + timedelta(hours=hours)).strftime("%H:%M") }} Uhr
              {% else %}Unbekannt{% endif %}
            {% endif %}{% endraw %}
          leistung: >
            {% raw %}{% set p = states('sensor.rct_power_storage_battery_power') | float(0) %}
            {% if p | abs >= 1000 %}
              {{ (p | abs / 1000) | round(2) }} kW
            {% else %}
              {{ p | abs | round(0) }} W
            {% endif %}{% endraw %}

Template-Sensor – v2.0 – +x Tage wenn die ETA länger wie 24 h ist

template:
    - sensor:
      - name: "Batterie-restzeit" # 20251209
        unique_id: batterie-restzeit
        state: >
          {% set power = states('sensor.rct_power_storage_battery_power') | float(0) %}
          {% if power | abs <= 5 %}
            Standby
          {% elif power < -5 %}
            Lädt
          {% else %}
            Entlädt
          {% endif %}
        icon: >
          {% set soc = states('sensor.rct_power_storage_battery_state_of_charge') | float(0) %}
          {% set power = states('sensor.rct_power_storage_battery_power') | float(0) %}

          {# --- Ladezustand prüfen --- #}
          {% if power < 0 %}
            {# Batterie lädt -> Ladeicon #}
            {% if soc >= 95 %}mdi:battery-charging-100
            {% elif soc >= 85 %}mdi:battery-charging-90
            {% elif soc >= 65 %}mdi:battery-charging-70
            {% elif soc >= 45 %}mdi:battery-charging-50
            {% elif soc >= 25 %}mdi:battery-charging-30
            {% elif soc >= 10 %}mdi:battery-charging-20
            {% else %}mdi:battery-charging-outline
            {% endif %}

          {% elif power > 0 %}
            {# Batterie entlädt -> normales Akkuicon #}
            {% if soc >= 95 %}mdi:battery
            {% elif soc >= 85 %}mdi:battery-90
            {% elif soc >= 65 %}mdi:battery-70
            {% elif soc >= 45 %}mdi:battery-50
            {% elif soc >= 25 %}mdi:battery-30
            {% elif soc >= 10 %}mdi:battery-20
            {% else %}mdi:battery-alert
            {% endif %}

          {% else %}
            {# Batterie weder lädt noch entlädt -> Idle Icon #}
            {% if soc >= 85 %}mdi:battery
            {% elif soc >= 65 %}mdi:battery-70
            {% elif soc >= 45 %}mdi:battery-50
            {% elif soc >= 25 %}mdi:battery-30
            {% elif soc >= 10 %}mdi:battery-20
            {% else %}mdi:battery-outline
            {% endif %}
          {% endif %}
        attributes:
          status: >
            {% set power = states('sensor.rct_power_storage_battery_power') | float(none) %}
            {% if power is none %}
              {% set power = this.attributes.power_last | float(0) %}
            {% else %}
              {% set power_last = power %}
            {% endif %}
            {% if power | abs <= 5 %}
              Standby
            {% elif power < -5 %}
              Lädt
            {% else %}
              Entlädt
            {% endif %}
          soc: >
            {% set soc = states('sensor.rct_power_storage_battery_state_of_charge') | float(none) %}
            {% if soc is none %}
              {% set soc = this.attributes.soc_last | float(0) %}
            {% else %}
              {% set soc_last = soc %}
            {% endif %}
            {{ soc | round(1) }}%
          restzeit: >
            {% set size = 7.5 %}
            {% set soc = states('sensor.rct_power_storage_battery_state_of_charge') | float(none) %}
            {% if soc is none %}
              {% set soc = this.attributes.soc_last | float(0) %}
            {% else %}
              {% set soc_last = soc %}
            {% endif %}

            {% set target = states('sensor.rct_power_storage_battery_state_of_charge_target') | float(100) %}

            {% set power_w = states('sensor.rct_power_storage_battery_power') | float(none) %}
            {% if power_w is none %}
              {% set power_w = this.attributes.power_last | float(0) %}
            {% else %}
              {% set power_last = power_w %}
            {% endif %}

            {% if power_w | abs <= 5 %}
              {{ "" }}
            {% else %}
              {% if power_w < -5 %}
                {% set e_diff = (target - soc) / 100 * size %}
              {% else %}
                {% set e_diff = (soc - 7) / 100 * size %}
              {% endif %}
              {% set hours = e_diff / (power_w | abs / 1000) %}
              {% if hours <= 0 %}
                Unbekannt
              {% else %}
                {% set total_minutes = (hours * 60) | round(0) %}
                {% set h = total_minutes // 60 %}
                {% set m = total_minutes % 60 %}
                {% if h > 0 %}{{ h }}h {{ "%02d"|format(m) }}min{% else %}{{ m }}min{% endif %}
              {% endif %}
            {% endif %}
          eta: >
            {% set size = 7.5 %}
            {% set soc = states('sensor.rct_power_storage_battery_state_of_charge') | float(none) %}
            {% if soc is none %}
              {% set soc = this.attributes.soc_last | float(0) %}
            {% else %}
              {% set soc_last = soc %}
            {% endif %}

            {% set target = states('sensor.rct_power_storage_battery_state_of_charge_target') | float(100) %}
            {% set power_w = states('sensor.rct_power_storage_battery_power') | float(none) %}
            {% if power_w is none %}
              {% set power_w = this.attributes.power_last | float(0) %}
            {% else %}
              {% set power_last = power_w %}
            {% endif %}

            {% if power_w | abs <= 5 %}
              {{ "" }}
            {% else %}
              {% if power_w < -5 %}
                {% set e_diff = (target - soc) / 100 * size %}
              {% else %}
                {% set e_diff = (soc - 7) / 100 * size %}
              {% endif %}

              {% set hours = e_diff / (power_w | abs / 1000) %}
              {% if hours <= 0 %}
                Unbekannt
              {% else %}
                {% if hours >= 24 %}
                  {% set days = (hours // 24) | int %}
                  {% set remaining_hours = (hours % 24) | int %}
                  {% set eta_time = (now() + timedelta(hours=remaining_hours)).strftime('%H:%M') %}
                  +{{ days }} Tage {{ eta_time }} Uhr
                {% else %}
                  {{ (now() + timedelta(hours=hours)).strftime('%H:%M') }} Uhr
                {% endif %}
              {% endif %}
            {% endif %}

          leistung: >
            {% set power = states('sensor.rct_power_storage_battery_power') | float(none) %}
            {% if power is none %}
              {% set power = this.attributes.power_last | float(0) %}
            {% else %}
              {% set power_last = power %}
            {% endif %}

            {% if power | abs >= 1000 %}
              {{ (power | abs / 1000) | round(2) }} kW
            {% else %}
              {{ power | abs | round(0) }} W
            {% endif %}

Lovelace Markdown-Karte Beispiel

type: markdown
title: Batterie Status
content: |
  **Status:** {{ state_attr('sensor.batterie_restzeit','status') }}
  ⚡ **SOC:** {{ state_attr('sensor.batterie_restzeit','soc') }}
  ⏱ **Restzeit:** {{ state_attr('sensor.batterie_restzeit','restzeit') }}
  ⏰ **ETA:** {{ state_attr('sensor.batterie_restzeit','eta') }}
  🔌 **Leistung:** {{ state_attr('sensor.batterie_restzeit','leistung') }}

ApexCharts Energie-Panel

type: custom:apexcharts-card
header:
  title: Batterie – Energieverlauf
graph_span: 6h
span:
  end: minute
now:
  show: true
  label: Jetzt
apex_config:
  chart:
    height: 320px
series:
  - entity: sensor.rct_power_storage_battery_power
    name: Leistung (W)
    type: area
    stroke_width: 2
    opacity: 0.3
    color: "#007bff"
    unit: W
  - entity: sensor.rct_power_storage_battery_state_of_charge
    name: Ladezustand (%)
    type: line
    curve: smooth
    stroke_width: 3
    color: "#28a745"
    yaxis_id: soc
yaxis:
  - id: main
    min: -5000
    max: 5000
    decimals: 0
  - id: soc
    opposite: true
    min: 0
    max: 100
    decimals: 0

Blueprint

blueprint:
  name: Batterie Monitor Sensor
  domain: template
  description: Erstellt einen intelligenten Batterie-Sensor mit Status, SOC, Restzeit und ETA.
  input:
    battery_power:
      name: Batterie Leistung (W)
      selector:
        entity:
          domain: sensor
    battery_soc:
      name: Batterie SOC (%)
      selector:
        entity:
          domain: sensor
    battery_soc_target:
      name: Ziel SOC (%)
      selector:
        entity:
          domain: sensor
    usable_capacity:
      name: Nutzbare Kapazität (kWh)
      default: 7.5
      selector:
        number:
          min: 1
          max: 30
          step: 0.1
template:
  - sensor:
      - name: Batterie Monitor
        unique_id: batterie_monitor_blueprint
        state: >
          {% raw %}{% set p = states(inputs.battery_power) | float(0) %}
          {% if p | abs <= 5 %}Standby
          {% elif p < -5 %}Lädt
          {% else %}Entlädt
          {% endif %}{% endraw %}
        attributes:
          soc: "{{ states(inputs.battery_soc) | float(0) }}"
          status: >
            {% raw %}{% set p = states(inputs.battery_power) | float(0) %}
            {% if p | abs <= 5 %}Standby
            {% elif p < -5 %}Lädt
            {% else %}Entlädt
            {% endif %}{% endraw %}
          leistung: >
            {% raw %}{% set p = states(inputs.battery_power) | float(0) %}
            {% if p | abs >= 1000 %}{{ (p | abs / 1000) | round(2) }} kW
            {% else %}{{ p | abs | round(0) }} W{% endif %}{% endraw %}
          restzeit: > {% raw %}...{% endraw %}
          eta: > {% raw %}...{% endraw %}