Anker 3 Solix einbinden

dauert es bei Euch auch “ewig” - also um die 5 Minuten - bis die Daten in HA aktualisiert werden?

*edit: Update Intervall steht auf 60 Sekunden, auch alle anderen Einstellungen sind auf Default Einstellungen

Hallo! Wie habt ihr das hinbekommen mit der täglichen PV Leistung. Die ist bei mir immer niedriger als in der APP und ich denke das es am Intervall liegt. Der Sensor Solarleistung wird ja auch alle paar Minuten aktualisiert obwohl der Update Intervall auf 60sek

lg
Flo

Anker Solix Nulleinspeisung mit Home Assistant – ohne Anker Smart Meter

Die eingebaute Nulleinspeisung der Solix funktioniert nur mit einem gekoppelten Smart Meter (Anker oder Shelly). Wer das nicht installieren kann oder will, hat mit Home Assistant eine vollwertige Alternative.

Meine Lösung: Ein Tasmota-Zähler am Hausanschluss liefert den Netzbezug, eine HA-Automation setzt daraus die Einspeisevorgabe der Solarbank – Ergebnis ist eine stabile Nulleinspeisung ohne zusätzliche Hardware im Sicherungskasten.

Zusätzliche Vorteile gegenüber der App-Lösung:

  • Kein Anker Smart Meter nötig

  • Akkumanagement nach Jahreszeit und Tageszeit

  • Prognosesteuerung via Solcast (nachts weniger entladen bei gutem Solartag morgen)

  • SOC-Schutz und Wintermodus

  • Spike-Filterung für kurze Lastspitzen

Voraussetzungen:

  • Home Assistant

  • Tasmota-fähiger Stromzähler (z.B. am IR-Lesekopf)

  • Anker Solix HA-Integration

alias: Anker Solix3 Nulleinspeisung
description: v5.5.8
triggers:
  - trigger: state
    entity_id: sensor.bezug_geglattet
    for:
      seconds: 2
  - trigger: state
    entity_id: sensor.tasmota_ehz_power
    for:
      seconds: 2
  - trigger: time_pattern
    seconds: /45
  - trigger: state
    entity_id: sensor.none_prognose_morgen
    for:
      seconds: 10
  - trigger: state
    entity_id: sensor.none_forecast_today_remaining
    for:
      seconds: 10
conditions:
  - condition: state
    entity_id: input_boolean.solarbank_automatik
    state: "on"
actions:
  - variables:
      sensor_bezug: sensor.bezug_geglattet
      sensor_bezug_roh: sensor.tasmota_ehz_power
      sensor_solarbank_soc: sensor.solarbank_3_e2700_pro_ladestand
      sensor_solarbank_solar: sensor.solarbank_3_e2700_pro_solarleistung
      sensor_solarbank_entladung: sensor.solarbank_3_e2700_pro_dc_ausgangsleistung
      number_solarbank_vorgabe: number.solarbank_3_e2700_pro_system_einspeisevorgabe
      sensor_forecast_morgen: sensor.none_prognose_morgen
      sensor_forecast_heute_rest: sensor.none_forecast_today_remaining
      RUNDUNG_WATT: 10
      RUNDUNG_WATT_KLEIN: 5
      EINSPEISUNG_SCHWELLE_WATT: -25
      MAX_LEISTUNG_ABSOLUT: 2000
      MAX_LEISTUNG_ANLAUF: 350
      SOLAR_ANLAUF_EIN: 130
      SOLAR_ANLAUF_AUS: 90
      SOC_KRITISCH: 8
      SOC_HYSTERESE: 2
      SPITZEN_SCHWELLE_WATT: 340
      SPITZEN_BESTAETIGUNG_FAKTOR: 0.68
      SPITZEN_SEHR_HOCH: 550
      HYST_BASE_WATT: 12
      HYST_MIN_WATT: 8
      HYST_MAX_WATT: 28
      VORGABE_CACHE_SEKUNDEN: 80
      NACHT_THROTTLE_SEKUNDEN: 300
      SOLAR_THROTTLE_SEKUNDEN: 120
      FORECAST_SEHR_GUT: 5
      FORECAST_GUT: 3
      FORECAST_MITTEL: 1.5
      FORECAST_VORSTEUERUNG_VIEL: 80
      FORECAST_VORSTEUERUNG_MITTEL: 40
      FORECAST_VORSTEUERUNG_SOC_MIN: 40
      REGELKORREKTUR_MIN_SHORTFALL: 60
      REGELKORREKTUR_FAKTOR: 0.22
      REGELKORREKTUR_CAP: 20
      REGELKORREKTUR_MAX_PROZENT: 0.07
      WINTER_MONATE:
        - 10
        - 11
        - 12
        - 1
        - 2
      WINTER_NACHT_FAKTOR: 0.75
      SOLAR_THROTTLE_SCHWELLE_EIN: 5
      SOLAR_THROTTLE_SCHWELLE_AUS: 15
      PUFFER_SOC_99: 50
      PUFFER_SOC_98: 30
      PUFFER_SOC_95: 20
      PUFFER_SOC_90: 10
      MAX_LEISTUNG_TAG_BASIS: 1000
  - variables:
      last_timestamp: >-
        {{ states('input_number.solarbank_letzte_vorgabe_timestamp') | float(0)
        }}
      seconds_since_last_set: >
        {% set diff = (now().timestamp() | float - last_timestamp) | float %} {{
        999 if diff < 0 or diff > 86400 else diff | int }}
  - if:
      - condition: template
        value_template: >
          {% set soc = states('sensor.solarbank_3_e2700_pro_ladestand') |
          float(99) %} {% set forecast = states('sensor.none_prognose_morgen') |
          float(0) %} {% set soc_aus_basis = 20 if now().month in [10,11,12,1,2]
          else 10 %} {% set soc_ausschalten = soc_aus_basis + (5 if forecast <
          1.5 else 3 if forecast < 3 else 0) %} {{ seconds_since_last_set < 30
          and soc > SOC_KRITISCH and soc > soc_ausschalten }}
    then:
      - stop: "Hard-Cooldown: 30s Minimum-Change-Delay"
  - variables:
      sun_elevation: "{{ state_attr('sun.sun', 'elevation') | float(-90) }}"
      ist_nacht: "{{ sun_elevation < -6 }}"
      ist_abend: "{{ sun_elevation < 15 and sun_elevation >= -6 }}"
      ist_winter: "{{ now().month in WINTER_MONATE }}"
  - variables:
      solar_raw: "{{ states(sensor_solarbank_solar) | float(0) }}"
      solar_throttle_ok: >-
        {{ states(sensor_solarbank_solar) not in ['unavailable', 'unknown',
        'none'] }}
  - choose:
      - conditions:
          - condition: template
            value_template: >-
              {{ solar_throttle_ok and solar_raw >= SOLAR_THROTTLE_SCHWELLE_AUS
              }}
        sequence:
          - action: input_boolean.turn_off
            target:
              entity_id: input_boolean.solar_kein_ertrag_aktiv
      - conditions:
          - condition: template
            value_template: >-
              {{ solar_throttle_ok and solar_raw < SOLAR_THROTTLE_SCHWELLE_EIN
              }}
        sequence:
          - action: input_boolean.turn_on
            target:
              entity_id: input_boolean.solar_kein_ertrag_aktiv
  - if:
      - condition: template
        value_template: >
          {% set ist_zeit_trigger = trigger.platform == 'time_pattern' %} {% set
          kein_ertrag = is_state('input_boolean.solar_kein_ertrag_aktiv', 'on')
          %} {% set diff = (now().timestamp() | float - last_timestamp) | float
          %} {% set throttle = NACHT_THROTTLE_SEKUNDEN if ist_nacht else
          (SOLAR_THROTTLE_SEKUNDEN if kein_ertrag else 0) %} {{ ist_zeit_trigger
          and throttle > 0 and last_timestamp > 0 and diff < throttle }}
    then:
      - stop: Throttle aktiv
  - variables:
      raw_bezug: "{{ states(sensor_bezug) }}"
      raw_bezug_roh: "{{ states(sensor_bezug_roh) }}"
      raw_soc: "{{ states(sensor_solarbank_soc) }}"
      raw_solar: "{{ states(sensor_solarbank_solar) }}"
      raw_entladung: "{{ states(sensor_solarbank_entladung) }}"
      raw_vorgabe: "{{ states(number_solarbank_vorgabe) }}"
      raw_forecast_morgen: "{{ states(sensor_forecast_morgen) }}"
      raw_forecast_heute_rest: "{{ states(sensor_forecast_heute_rest) }}"
      sensor_ok: |
        {{ raw_bezug not in ['unavailable','unknown','none'] and
           raw_soc not in ['unavailable','unknown','none'] and
           raw_solar not in ['unavailable','unknown','none'] and
           raw_entladung not in ['unavailable','unknown','none'] }}
  - if:
      - condition: template
        value_template: "{{ not sensor_ok }}"
    then:
      - action: system_log.write
        data:
          message: Solarbank v5.5.8 Sensor error detected
          level: warning
      - stop: Sensor error
  - if:
      - condition: state
        entity_id: input_boolean.solarbank_fehler_gemeldet
        state: "on"
    then:
      - action: input_boolean.turn_off
        target:
          entity_id: input_boolean.solarbank_fehler_gemeldet
      - action: persistent_notification.dismiss
        data:
          notification_id: solarbank_sensor_fehler
  - variables:
      bezug_watt: "{{ raw_bezug | float(0) }}"
      bezug_roh_watt: "{{ raw_bezug_roh | float(0) }}"
      soc_prozent: "{{ raw_soc | float(0) }}"
      solar_watt: "{{ raw_solar | float(0) }}"
      entladung_watt: "{{ raw_entladung | float(0) }}"
      vorgabe_watt: "{{ raw_vorgabe | float(0) }}"
      forecast_morgen_kwh: "{{ raw_forecast_morgen | float(0) }}"
      forecast_heute_rest_kwh: "{{ raw_forecast_heute_rest | float(0) }}"
      bezug_delta: "{{ (bezug_roh_watt - bezug_watt) | abs }}"
      spitze_erkannt: >
        {% if bezug_roh_watt <= 0 %}false {% elif bezug_delta >
        SPITZEN_SEHR_HOCH %}true {% elif bezug_delta > SPITZEN_SCHWELLE_WATT %}
          {{ not (bezug_watt > 12 and (bezug_roh_watt / bezug_watt) >= SPITZEN_BESTAETIGUNG_FAKTOR) }}
        {% else %}false{% endif %}
      bezug_effektiv: >
        {% if spitze_erkannt %}{{ bezug_watt }} {% elif bezug_delta <=
        SPITZEN_SCHWELLE_WATT + 30 %}{{ bezug_roh_watt }} {% else %}{{
        bezug_watt }}{% endif %}
      forecast_morgen_cat: >
        {% if forecast_morgen_kwh >= FORECAST_SEHR_GUT %}SEHR_GUT {% elif
        forecast_morgen_kwh >= FORECAST_GUT %}GUT {% elif forecast_morgen_kwh >=
        FORECAST_MITTEL %}MITTEL {% else %}SCHLECHT{% endif %}
      forecast_heute_cat: >
        {% if forecast_heute_rest_kwh >= 3 %}VIEL {% elif
        forecast_heute_rest_kwh >= 1.5 %}MITTEL {% else %}WENIG{% endif %}
      soc_aus_basis: "{{ 20 if ist_winter else 10 }}"
      soc_regel_basis: "{{ 25 if ist_winter else 15 }}"
      soc_ausschalten: >
        {% if forecast_morgen_cat == 'SEHR_GUT' %}{{ [soc_aus_basis - 2, 5] |
        max }} {% elif forecast_morgen_cat == 'GUT' %}{{ soc_aus_basis }} {%
        elif forecast_morgen_cat == 'MITTEL' %}{{ soc_aus_basis + 3 }} {% else
        %}{{ soc_aus_basis + 5 }}{% endif %}
      soc_einschalten: >-
        {{ [soc_ausschalten + SOC_HYSTERESE, SOC_KRITISCH + SOC_HYSTERESE + 1] |
        max }}
      soc_regelstart: >
        {% if forecast_morgen_cat == 'SEHR_GUT' %}{{ soc_regel_basis - 1 }} {%
        elif forecast_morgen_cat == 'SCHLECHT' %}{{ soc_regel_basis + 3 }} {%
        else %}{{ soc_regel_basis }}{% endif %}
      betriebsmodus: |
        {%- if soc_prozent <= SOC_KRITISCH -%}
          KRITISCH
        {%- elif soc_prozent <= soc_ausschalten -%}
          AUSSCHALTEN
        {%- elif soc_prozent < soc_einschalten -%}
          {%- if solar_watt >= SOLAR_ANLAUF_EIN -%}ANLAUF_SOLAR{%- else -%}GESPERRT{%- endif -%}
        {%- elif soc_prozent < soc_regelstart -%}
          ANLAUF
        {%- elif ist_abend and soc_prozent >= 80 -%}
          ABEND_BOOST
        {%- else -%}
          NORMAL
        {%- endif -%}
      max_leistung_nacht: |
        {% if forecast_morgen_cat == 'SEHR_GUT' %}
          {{ 500 if soc_prozent >= 70 else 400 if soc_prozent >= 50 else 250 if soc_prozent >= 30 else 150 }}
        {% elif forecast_morgen_cat == 'GUT' %}
          {{ 350 if soc_prozent >= 60 else 300 if soc_prozent >= 40 else 150 }}
        {% else %}150{% endif %}
      max_leistung_nacht_final: >-
        {{ (max_leistung_nacht * WINTER_NACHT_FAKTOR) | int if ist_winter else
        max_leistung_nacht | int }}
      max_entladeleistung: >
        {% if ist_nacht and forecast_morgen_cat == 'SCHLECHT' and soc_prozent <
        35 %}110 {% elif ist_nacht %}{{ max_leistung_nacht_final }} {% elif
        ist_abend %}{{ 800 if forecast_heute_cat == 'VIEL' else 600 }} {% elif
        betriebsmodus == 'ANLAUF' %}{{ MAX_LEISTUNG_ANLAUF }} {% else %}{{
        MAX_LEISTUNG_TAG_BASIS }}{% endif %}
  - if:
      - condition: template
        value_template: >
          {{ states('input_text.solarbank_letzter_modus') | default('') !=
          betriebsmodus and
             states('input_text.solarbank_letzter_modus') != '' }}
    then:
      - action: system_log.write
        data:
          message: >-
            Solarbank v5.5.8 Mode: {{
            states('input_text.solarbank_letzter_modus') }} → {{ betriebsmodus
            }}
          level: warning
  - action: input_text.set_value
    target:
      entity_id: input_text.solarbank_letzter_modus
    data:
      value: "{{ betriebsmodus }}"
  - variables:
      aktuelle_vorgabe: >
        {% set gemerkt = states('input_number.solarbank_letzte_vorgabe_wert') |
        float(-1) %} {% set diff = (now().timestamp() | float - last_timestamp)
        | float %} {% set cache_ok = last_timestamp > 0 and 0 <= diff <
        VORGABE_CACHE_SEKUNDEN %} {{ vorgabe_watt if betriebsmodus in
        ['KRITISCH', 'AUSSCHALTEN'] else (gemerkt if gemerkt >= 0 and cache_ok
        else vorgabe_watt) }}
      puffer_basis: >
        {% if soc_prozent >= 99 %}{{ PUFFER_SOC_99 }} {% elif soc_prozent >= 98
        %}{{ PUFFER_SOC_98 }} {% elif soc_prozent >= 95 %}{{ PUFFER_SOC_95 }} {%
        elif soc_prozent >= 90 %}{{ PUFFER_SOC_90 }} {% else %}0{% endif %}
      puffer_faktor: >-
        {{ 1.5 if forecast_morgen_cat == 'SEHR_GUT' else 1.2 if
        forecast_morgen_cat == 'GUT' else 1.0 }}
      puffer_watt: >
        {% set basis = (puffer_basis * puffer_faktor) | int %} {% if soc_prozent
        >= 95 %}
          {% if forecast_morgen_cat == 'SEHR_GUT' %}{{ (basis * 0.55) | int }}
          {% elif forecast_morgen_cat == 'GUT' %}{{ (basis * 0.75) | int }}
          {% else %}{{ (basis * 1.30) | int }}{% endif %}
        {% else %}{{ basis }}{% endif %}
      forecast_vorsteuerung: >
        {% if betriebsmodus not in ['NORMAL', 'ABEND_BOOST', 'ANLAUF'] or
        ist_nacht or soc_prozent < FORECAST_VORSTEUERUNG_SOC_MIN %}0 {% elif
        forecast_heute_cat == 'VIEL' and soc_prozent >= 60 %}{{
        FORECAST_VORSTEUERUNG_VIEL }} {% elif forecast_heute_cat == 'MITTEL' and
        soc_prozent >= 50 %}{{ FORECAST_VORSTEUERUNG_MITTEL }} {% else %}0{%
        endif %}
      regelabweichung: "{{ aktuelle_vorgabe - entladung_watt }}"
      regelkorrektur: >
        {% if betriebsmodus not in ['NORMAL', 'ABEND_BOOST'] or regelabweichung
        <= REGELKORREKTUR_MIN_SHORTFALL %}0 {% else %}{{ [[(regelabweichung *
        REGELKORREKTUR_FAKTOR) | int, REGELKORREKTUR_CAP] | min,
        (aktuelle_vorgabe * REGELKORREKTUR_MAX_PROZENT) | int] | min }}{% endif
        %}
      p_regler_ziel: >-
        {{ (aktuelle_vorgabe + bezug_effektiv + puffer_watt +
        forecast_vorsteuerung + regelkorrektur) | int }}
      ziel_leistung_roh: >
        {% if betriebsmodus in ['KRITISCH', 'AUSSCHALTEN', 'GESPERRT'] %}0 {%
        elif betriebsmodus == 'ANLAUF_SOLAR' %}
          {% set solar_limit = (solar_watt * 0.88) | int %}
          {% set ziel = [0, [p_regler_ziel, solar_limit] | min] | max %}
          {% set rundung = RUNDUNG_WATT_KLEIN if ziel < 100 else RUNDUNG_WATT %}
          {{ ((ziel / rundung) | round(0) * rundung) | int }}
        {% else %}
          {% set ziel = [0, [p_regler_ziel, max_entladeleistung] | min] | max %}
          {% set rundung = RUNDUNG_WATT_KLEIN if ziel < 100 else RUNDUNG_WATT %}
          {{ ((ziel / rundung) | round(0) * rundung) | int }}
        {% endif %}
      ziel_leistung_final: "{{ [0, [ziel_leistung_roh, MAX_LEISTUNG_ABSOLUT] | min] | max }}"
      hysterese_watt: >
        {% set base = HYST_BASE_WATT %} {% set prop = (aktuelle_vorgabe * 0.045)
        | round(0) | int %} {{ [HYST_MIN_WATT, [base, prop] | max,
        HYST_MAX_WATT] | min }}
      abweichung: "{{ (ziel_leistung_final - aktuelle_vorgabe) | abs }}"
      seconds_since_update: >
        {% set diff = (now().timestamp() | float - last_timestamp) | float %} {{
        999 if last_timestamp == 0 or diff < 0 or diff > 86400 else diff }}
      cooldown_effektiv: >
        {%- if betriebsmodus in ['KRITISCH','AUSSCHALTEN','GESPERRT'] -%}0 {%-
        elif betriebsmodus == 'ANLAUF_SOLAR' -%}25 {%- elif bezug_effektiv <
        EINSPEISUNG_SCHWELLE_WATT -%}15 {%- elif abweichung > 250 -%}55 {%- elif
        abweichung > 120 -%}45 {%- elif abweichung > 40 -%}35 {%- else -%}95{%-
        endif -%}
      soll_aendern: |
        {{ ziel_leistung_final != aktuelle_vorgabe and
           (abweichung >= hysterese_watt or bezug_effektiv < EINSPEISUNG_SCHWELLE_WATT or
            betriebsmodus in ['KRITISCH','AUSSCHALTEN','ANLAUF_SOLAR','GESPERRT']) and
           seconds_since_last_set >= 30 and
           seconds_since_update > cooldown_effektiv }}
  - if:
      - condition: template
        value_template: "{{ soll_aendern }}"
    then:
      - action: number.set_value
        target:
          entity_id: "{{ number_solarbank_vorgabe }}"
        data:
          value: "{{ ziel_leistung_final }}"
      - action: input_number.set_value
        target:
          entity_id: input_number.solarbank_letzte_vorgabe_timestamp
        data:
          value: "{{ now().timestamp() | int }}"
      - action: input_number.set_value
        target:
          entity_id: input_number.solarbank_letzte_vorgabe_wert
        data:
          value: "{{ ziel_leistung_final }}"
      - choose:
          - conditions:
              - condition: state
                entity_id: input_boolean.solarbank_debug
                state: "on"
            sequence:
              - action: system_log.write
                data:
                  message: >
                    Solarbank v5.5.8 [DEBUG] {{ aktuelle_vorgabe }}W → {{
                    ziel_leistung_final }}W H{{ hysterese_watt }} Δ{{ abweichung
                    }} {{ betriebsmodus }} SOC{{ soc_prozent }}%
                  level: debug
          - conditions: []
            sequence:
              - action: system_log.write
                data:
                  message: >
                    Solarbank v5.5.8 ✅ {{ aktuelle_vorgabe }}W → {{
                    ziel_leistung_final }}W | {{ betriebsmodus }} | SOC: {{
                    soc_prozent }}% {%- if ziel_leistung_final >=
                    MAX_LEISTUNG_ABSOLUT %} ⚠️ capped{% endif %}
                  level: info
mode: single
max_exceeded: silent

In der Anker App steht das auf Eigenverbrauch und damit regelt die Anker SB ziemlich exakt auf Null. Ohne HA Automatisierung.

Die Solix-App läuft bei mir im Eigenverbrauch-Modus. Die eigentliche Nulleinspeisung übernimmt aber eine HA-Automation, die die Einspeisevorgabe dynamisch an den aktuellen Hausverbrauch anpasst.