MYPV integration started

@ showup: Thanks for your great work…

Thank you for the nice script.

Does anybody now if I can I read energy and power metrics for each output separately?

What differentiates MYPV integration started - #54 by showup from this HA integration?

… your work!

I don’t know if you got a solution on how to read energy and power for each output. The easyest way is to install one power/energy meter on each output. Simple solutions are better than try and error. As sleepymaxx wrote…(and yes i recommend to read the whole article top to bottom).

I recommend to use this HA integration, I’m maintaining it regularly: GitHub - dneprojects/mypv: Home Assistant custom integration for myPV devices

1 Like

Hallo zusammen, ich musste meinen Home assistant komplett umbauen, dabe habe ich aus der gesamten sache von oben einen Bluprint erstellt welche nun beide Automatisierungen ersetzen kann. mfg

blueprint:
  name: ELWA Pro - Ultimate (Watt-Logik, Nachtsperre & Flex-Schwelle)
  description: "Stabile 0.9-Logik. Nutzt negative Watt-Werte (Einspeisung) und besitzt eine Sonnenstands-Sperre."
  domain: automation
  input:
    smart_meter_export:
      name: Smart-Meter Export (Watt)
      description: "Sensor für den Netz-Zähler. Einspeisung MUSS negativ sein (z.B. -500W)."
      default: sensor.smart_meter_summe_der_aktiven_momentanleistung
      selector:
        entity:
          domain: sensor
    battery_discharge:
      name: Batterie Entladung (kW)
      default: sensor.master_battery_discharge
      selector:
        entity:
          domain: sensor
    elwa_consumption:
      name: ELWA Aktueller Verbrauch (Watt)
      default: sensor.elwa_e_2_mypv_stromverbrauch_aktuell
      selector:
        entity:
          domain: sensor
    elwa_temp_top:
      name: Temperatur oben
      default: sensor.elwa_e_2_trinkwasser_temperatur_oben
      selector:
        entity:
          domain: sensor
    elwa_temp_bottom:
      name: Temperatur unten
      default: sensor.elwa_e_2_trinkwasser_temperatur_unten
      selector:
        entity:
          domain: sensor
    timer_helper:
      name: Timer-Helfer für Pause
      default: timer.elwa_pause
      selector:
        entity:
          domain: timer
    temp_max:
      name: Max. Temperatur oben
      default: 60
      selector:
        number:
          min: 53
          max: 67
          step: 1
          unit_of_measurement: "°C"
    temp_freigabe_oben:
      name: Freigabe oben
      default: 53
      selector:
        number:
          min: 45
          max: 60
          step: 1
          unit_of_measurement: "°C"
    temp_freigabe_unten:
      name: Freigabe unten
      default: 40
      selector:
        number:
          min: 30
          max: 45
          step: 1
          unit_of_measurement: "°C"
    export_threshold:
      name: Einspeise-Schwelle (Watt)
      description: "Ab wie viel Watt Einspeisung soll die ELWA starten? (Positiver Wert, z.B. 4)"
      default: 10
      selector:
        number:
          min: 5
          max: 45
          step: 1
          unit_of_measurement: "W"
    pause_time:
      name: Pausenzeit (min)
      default: 60
      selector:
        number:
          min: 30
          max: 180
          step: 1
          unit_of_measurement: "min"

mode: single

triggers:
  - trigger: state
    entity_id: !input smart_meter_export
  - trigger: state
    entity_id: !input battery_discharge
  - trigger: state
    entity_id: !input elwa_temp_top

# Marker 1: Nur bei Tag ausführen (wie in der Original-Automation)
conditions:
  - condition: sun
    after: sunrise
    before: sunset

actions:
  - variables:
      timer_ent: !input timer_helper
      top_ent: !input elwa_temp_top
      bot_ent: !input elwa_temp_bottom
      export_ent: !input smart_meter_export
      elwa_ent: !input elwa_consumption
      # Schwellenwerte
      threshold: !input export_threshold
      t_freigabe_o: !input temp_freigabe_oben
      t_freigabe_u: !input temp_freigabe_unten
      t_max: !input temp_max
      p_time: !input pause_time
      
      temp_oben: "{{ states(top_ent) | float(0) }}"
      temp_unten: "{{ states(bot_ent) | float(0) }}"
      is_paused: "{{ not is_state(timer_ent, 'idle') }}"
      needs_heat: "{{ temp_oben < (t_freigabe_o | float) or temp_unten < (t_freigabe_u | float) }}"

  # 1. PAUSE ABBRECHEN bei Bedarf
  - if:
      - condition: template
        value_template: "{{ is_paused and needs_heat }}"
    then:
      - action: timer.finish
        target:
          entity_id: !input timer_helper

  # 2. HAUPT-ENTSCHEIDUNG
  - choose:
      # FALL A: Max-Temperatur erreicht
      - conditions:
          - condition: template
            value_template: "{{ temp_oben >= (t_max | float) }}"
        sequence:
          - action: rest_command.update_elwa_power
            data:
              power: 0
          - if:
              - condition: template
                value_template: "{{ is_state(timer_ent, 'idle') }}"
            then:
              - action: timer.start
                target:
                  entity_id: !input timer_helper
                data:
                  duration: "{{ (p_time | int * 60) }}"

      # FALL B: Regelbetrieb
      - conditions:
          - condition: template
            value_template: "{{ is_state(timer_ent, 'idle') or needs_heat }}"
        sequence:
          - if:
              - condition: numeric_state
                entity_id: !input battery_discharge
                below: 0.16
              # Dynamische Prüfung auf negativen Wert (Einspeisung)
              - condition: template
                value_template: "{{ (states(export_ent) | float(0)) < (threshold | float * -1) }}"
            then:
              - action: rest_command.update_elwa_power
                data:
                  power: >-
                    {% set exp = states(export_ent) | float(0) %}
                    {% set cons = states(elwa_ent) | float(0) %}
                    {# exp ist negativ, daher * -1 um positive Watt zu erhalten. Dann Schwelle abziehen. #}
                    {{ (((exp * -1 - (threshold | float)) + cons) * 0.93) | round(0) }}
            else:
              - action: rest_command.update_elwa_power
                data:
                  power: 0

    default:
      - action: rest_command.update_elwa_power
        data:
          power: 0

Again i redesingnt the whole steering - biggest rules! 1: not Battery drain 2: no Grid use 3. maximum availabe Engery for the Elwa.
!! Change All ip´s to your Needs !!
!! Change All names(of your Sensors) to your Needs !!
you have to add the following Helper in HA:
Timer Helper: timer.elwa_pause
you have to use the rest integration (Get it throug HACS)
You have to add this to your config.yaml (the used Sensors/input commands)

modbus: !include modbus.yaml

You have to add this to your modbus.yaml (the used Sensors/input commands)

# Config modbus MYPV-Meter

- name: elwa_hub
  type: tcp
  host: 192.168.2.60
  port: 502
  retry_on_empty: true
  delay: 2
  timeout: 5
  message_wait_milliseconds: 200
  sensors:
    - name: "Elwa E 2 MyPV Stromverbrauch aktuell"
      unique_id: "elwa_e2_modbus_power"
      address: 1000
      slave: 1
      unit_of_measurement: "W" # Modbus liefert meist Watt
      device_class: power
      state_class: measurement
      scan_interval: 3

    - name: "Elwa E 2 Trinkwasser Temperatur unten"
      unique_id: "elwa_e2_modbus_temp_unten"
      address: 1001
      slave: 1
      unit_of_measurement: "°C"
      device_class: temperature
      scale: 0.1 # Modbus liefert Ganzzahlen (z.B. 255 für 25,5°C)
      precision: 1
      scan_interval: 30

    - name: "Elwa E 2 Trinkwasser Temperatur Oben"
      unique_id: "elwa_e2_modbus_temp_oben"
      address: 1030
      slave: 1
      unit_of_measurement: "°C"
      device_class: temperature
      scale: 0.1
      precision: 1
      scan_interval: 30

  number:
    - name: "Elwa E 2 Max Power Setting"
      unique_id: "elwa_e2_maxpwr_limit"
      address: 1017 # Register für Max Power (siehe MyPV Handbuch)
      slave: 1
      min_value: 0
      max_value: 3500
      step: 100
      unit_of_measurement: "W"

And you have to Add this Blueprint:

blueprint:
  name: ELWA Pro - Hybrid Ultimate
  description: "Dynamische Volatilitätsdämpfung, Temperatur-Freigabe oben/unten, robuste Sanitierung und stabile Pause-Logik. Grundregeln: 1) keine Batterieentladung 2) kein Netzbezug 3) maximale Überschussnutzung bei Warmwasserbedarf 4) adaptive Reserve bei Wolkenwechsel 5) stabile Logik."
  domain: automation
  input:
    smart_meter_export:
      name: Smart-Meter Export (Watt)
      description: "Einspeisung MUSS negativ sein (z.B. -500W)."
      default: sensor.smart_meter_summe_der_aktiven_momentanleistung
      selector:
        entity:
          domain: sensor
    volatility_sensor:
      name: Volatilitäts-Sensor (Statistics)
      description: "Sensor für die Standardabweichung des Netzes."
      default: sensor.smart_meter_netz_volatilitaet_1min
      selector:
        entity:
          domain: sensor
    battery_discharge:
      name: Batterie Entladung (kW)
      description: "Sensor in kW (z.B. 0.05 für 50W)."
      default: sensor.master_battery_discharge
      selector:
        entity:
          domain: sensor
    battery_charge:
      name: Batterie Ladung (kW)
      description: "Sensor für die aktuelle Ladeleistung in kW."
      default: sensor.master_battery_charge
      selector:
        entity:
          domain: sensor
    elwa_consumption:
      name: ELWA Aktueller Verbrauch (Watt)
      default: sensor.elwa_e2_modbus_power
      selector:
        entity:
          domain: sensor
    elwa_temp_top:
      name: Temperatur oben
      default: sensor.elwa_e2_modbus_temp_oben
      selector:
        entity:
          domain: sensor
    elwa_temp_bottom:
      name: Temperatur unten
      default: sensor.elwa_e2_modbus_temp_unten
      selector:
        entity:
          domain: sensor
    timer_helper:
      name: Timer-Helfer für Pause
      default: timer.elwa_pause
      selector:
        entity:
          domain: timer
    temp_max:
      name: Max. Temperatur oben
      default: 60
      selector:
        number:
          min: 53
          max: 67
          unit_of_measurement: "°C"
    temp_freigabe_oben:
      name: Freigabe Temperatur oben
      description: "Unter diesem Wert wird die Pause ignoriert (oben)."
      default: 53
      selector:
        number:
          min: 45
          max: 60
          unit_of_measurement: "°C"
    temp_freigabe_unten:
      name: Freigabe Temperatur unten
      description: "Unter diesem Wert wird die Pause ignoriert (unten)."
      default: 34
      selector:
        number:
          min: 30
          max: 40
          unit_of_measurement: "°C"
    reserve_min:
      name: Minimale Reserve (Watt)
      description: "Sicherheitsabstand bei Kaiserwetter."
      default: 40
      selector:
        number:
          min: 0
          max: 50
    reserve_max:
      name: Maximale Reserve (Watt)
      description: "Sicherheitsabstand bei Wolken-Chaos."
      default: 400
      selector:
        number:
          min: 50
          max: 2000
    battery_discharge_limit:
      name: Max. Batterie-Entladeschwelle (Watt)
      description: "Ab wie viel Watt Entladung soll die ELWA stoppen? (Bereich 10-40W). Hinweis: battery_discharge ist in kW."
      default: 32
      selector:
        number:
          min: 10
          max: 40
          unit_of_measurement: "W"
    pause_time:
      name: Pausenzeit (min)
      default: 60
      selector:
        number:
          min: 30
          max: 180

mode: restart
#mode: queued
#max: 2

triggers:
  - trigger: state
    entity_id: !input smart_meter_export
  - trigger: state
    entity_id: !input battery_discharge
  - trigger: state
    entity_id: !input elwa_temp_top
  - trigger: state
    entity_id: !input elwa_temp_bottom

conditions:
  - condition: sun
    after: sunrise
    before: sunset

actions:
  - variables:
      # Entity-Referenzen (YAML-Variablen, NICHT in Jinja)
      export_entity: !input smart_meter_export
      batt_entity: !input battery_discharge
      batt_charge_entity: !input battery_charge      
      vola_entity: !input volatility_sensor
      elwa_entity: !input elwa_consumption
      temp_o_entity: !input elwa_temp_top
      temp_u_entity: !input elwa_temp_bottom
      timer_entity: !input timer_helper
      
      hub_name: "elwa_hub" # Name aus deiner modbus configuration.yaml

      # Rohwerte sicher auslesen (Jinja mit entity-Variablen)
      export_val: "{{ states(export_entity) | float(0) }}"
      batt_val: "{{ states(batt_entity) | float(0) }}"
      vola_val: "{{ states(vola_entity) | float(0) }}"
      elwa_cons: "{{ states(elwa_entity) | float(0) }}"
      temp_o: "{{ states(temp_o_entity) | float(0) }}"
      temp_u: "{{ states(temp_u_entity) | float(0) }}"
      batt_charge_val: "{{ states(batt_charge_entity) | float(0) * 1000 }}"

      # Parameter
      p_time: !input pause_time
      batt_limit_w: !input battery_discharge_limit
      batt_limit_kw: "{{ (batt_limit_w | float) / 1000 }}"
      t_max: !input temp_max
      t_freig_o: !input temp_freigabe_oben
      t_freig_u: !input temp_freigabe_unten
      x_res: !input reserve_max
      y_res: !input reserve_min

      # Volatilitätsfaktor (angepasst, 0..1)
      vola_factor: "{{ [ (vola_val | float(0)) / 800, 0.98 ] | min }}"

      # Dynamische Reserve (skaliert zwischen y_res und x_res)
      dynamic_reserve: "{{ (y_res | float) + (vola_factor * ((x_res | float) - (y_res | float))) }}"

      # Status-Flags (robust)
      is_too_hot: "{{ (temp_o | float) >= (t_max | float) }}"
      is_grid_draw: "{{ (export_val | float) > 0 }}"
      is_batt_drain: "{{ (batt_val | float) > (batt_limit_kw | float) }}"
      is_paused: "{{ is_state(timer_entity, 'active') }}"
      is_batt_charging: "{{ batt_charge_val > 10 }}"

      # Bedarf an Wärme: untere Temp und, obere Temp
      needs_heat: >-
        {{ (temp_u | float) < (t_freig_u | float) or 
           (temp_o | float) < (t_freig_o | float) }}

  # 1) Pause sofort beenden, wenn Wasser zu kalt ist (Priorität Warmwasser)
  - if:
      - condition: template
        value_template: "{{ is_paused and needs_heat }}"
    then:
      - action: timer.finish
        target:
          entity_id: !input timer_helper

# 2) Entscheidungslogik (Hier wird Fall A und Fall B abgehandelt)
  - choose:
      # FALL A: Sofort-Stopp (Hitze, Netzbezug oder Batterie-Entladung)
      - conditions:
          - condition: template
            value_template: "{{ is_too_hot or is_grid_draw or is_batt_drain or is_batt_charging}}"
        sequence:
          - action: modbus.write_register
            data:
              hub: "{{ hub_name }}"
              address: 1000
              slave: 1
              value: 0
          - if:
              - condition: template
                value_template: "{{ is_too_hot and not is_paused }}"
            then:
              - action: timer.start
                target:
                  entity_id: !input timer_helper
                data:
                  duration: "{{ (p_time | int) * 60 }}"

      # FALL B: Regelbetrieb (Hier ist die neue "Option A" Logik integriert!)
      - conditions:
          - condition: template
            value_template: >-
                {{ (not is_grid_draw and not is_batt_drain and not is_batt_charging) and (not is_paused or needs_heat) }}
        sequence:
          - action: modbus.write_register
            data:
              hub: "{{ hub_name }}"
              address: 1000
              slave: 1
              value: >-
                {# 1. Echter Gesamt-Überschuss = Einspeisung (invertiert) + aktueller ELWA-Verbrauch #}
                {% set total_available = (export_val * -1) + elwa_cons %}
                
                {# 2. Abzug der Reserve & Sicherheitsfaktor #}
                {% set raw_final = (total_available - dynamic_reserve) * 0.98 %}
                
                {# 3. Ergebnis-Ausgabe #}
                {% set final_power = (raw_final | float(0)) | round(0) | int %}
                {{ [0, final_power] | max }}

    default:
      - action: modbus.write_register
        data:
          hub: "{{ hub_name }}"
          address: 1000
          slave: 1
          value: 0

If you want you can add this to your DASHBOARD for debug/graphic control:

type: vertical-stack
cards:
  - type: horizontal-stack
    cards:
      - type: gauge
        entity: sensor.smart_meter_summe_der_aktiven_momentanleistung
        name: Netz (Watt)
        min: -5000
        max: 5000
        severity:
          green: -5000
          yellow: 0
          red: 100
        needle: true
      - type: gauge
        entity: sensor.elwa_e_2_mypv_stromverbrauch_aktuell
        name: ELWA Ist
        min: 0
        max: 3500
        severity:
          green: 500
          yellow: 2500
          red: 3200
        needle: true
        unit: W
      - type: gauge
        entity: sensor.smart_meter_netz_volatilitaet_1min
        min: 0
        max: 100
        needle: true
        unit: "%"
        severity:
          green: 20
          yellow: 40
          red: 60
        name: Lastwechsel
  - type: history-graph
    entities:
      - entity: sensor.elwa_e_2_mypv_stromverbrauch_aktuell
    hours_to_show: 1
    refresh_interval: 10
  - type: entities
    title: Energie
    entities:
      - entity: timer.elwa_pause
        name: Pausen-Timer (Sperre)
        secondary_info: last-changed
      - entity: sensor.elwa_e_2_mypv_stromverbrauch_aktuell
        name: ELWA Leistung (W)
      - entity: sensor.smart_meter_summe_der_aktiven_momentanleistung
        name: Smart-Meter (W)
      - entity: sensor.master_battery_discharge
        name: Batterie Entladung (kW)
      - entity: sensor.master_battery_charge
        name: Batterie Ladung (kW)
  - type: entities
    title: Temperaturen
    entities:
      - entity: sensor.elwa_e_2_trinkwasser_temperatur_oben
        name: Temperatur oben (°C)
      - entity: sensor.elwa_e_2_trinkwasser_temperatur_unten
        name: Temperatur unten (°C)
  - type: custom:mushroom-template-card
    primary: Entscheidungslogik
    secondary: >
      {% set smart =
      states('sensor.smart_meter_summe_der_aktiven_momentanleistung') | float(0)
      %} {% set batt_dis = states('sensor.master_battery_discharge') | float(0)
      %} {% set batt_chg = states('sensor.master_battery_charge') | float(0) %}
      {% set temp_top = states('sensor.elwa_e_2_trinkwasser_temperatur_oben') |
      float(0) %} {% set temp_bot =
      states('sensor.elwa_e_2_trinkwasser_temperatur_unten') | float(0) %} {%
      set pv = (smart * -1) if smart < 0 else 0 %} {% set reserve = 100 %}

      {% if temp_top >= 60 %}
        Temperatur-Pause aktiv
      {% elif batt_dis > 0.01 %}
        Batterie-Schutz aktiv
      {% elif smart > 0 %}
        Netz-Schutz aktiv
      {% elif pv <= (batt_chg * 1000 + reserve) %}
        Kein echter PV-Überlauf
      {% elif temp_top < 55 or temp_bot < 45 %}
        ✔ ELWA darf heizen
      {% else %}
        Bedingungen nicht erfüllt
      {% endif %}
    icon: mdi:shield-check
    icon_color: >
      {% set temp_top = states('sensor.elwa_e_2_trinkwasser_temperatur_oben') |
      float(0) %} {% if temp_top >= 60 %}
        amber
      {% else %}
        blue
      {% endif %}

Afterwards config your Blueprint and have fun!

@sleepymaxx

Looks like you are still fight about the Elwa :slight_smile:
I move my system to Modbus TCP device respond is better and by far all the system works better

modbus:
  - name: ELWA
    type: tcp
    host: 192.168.1.200
    port: 502
    delay: 2
    timeout: 5
    message_wait_milliseconds: 200

    sensors:
      - name: "ELWA_Power"
        slave: 1
        address: 1000
        input_type: holding
        unit_of_measurement: "W"
        scan_interval: 10

      - name: "ELWA_Temp"
        slave: 1
        address: 1001
        input_type: holding
        scale: 0.1
        unit_of_measurement: "°C"
        scan_interval: 10

      - name: "ELWA_Target"
        slave: 1
        address: 1002
        input_type: holding
        scale: 0.1
        unit_of_measurement: "°C"
        scan_interval: 10

P.S. I try your blueprint above… Nice work.

nO figth … only interest … and NERDism … :wink:
how have you integrated the second Temperatrue … and why do you use it as a target temp?
How have you rewritten your Automation? – will try it also out —
Great idea! … modbus is way more practically ( only your timeout is a little much? )

Sorry for the delay…I was away for a few days. Well the target temp it only show where is the setup temp of the elwa. Nothing special. The automation is here:

alias: ElwaUpdate
description: ElwaUpdate
triggers:
  - entity_id: sensor.vxxout
    trigger: state
conditions:
  - condition: numeric_state
    entity_id: sensor.vxxout
    above: 800
  - condition: numeric_state
    entity_id: sensor.elwaxx_temp
    below: 55
  - condition: template
    value_template: >
      {% set last_triggered = state_attr('automation.elwaupdate',
      'last_triggered') %} {{ last_triggered is none or (now() -
      last_triggered).total_seconds() > 60 }}
  - condition: state
    entity_id: input_boolean.elwaupdate_running
    state: "off"
actions:
  - target:
      entity_id: input_boolean.elwaupdate_running
    action: input_boolean.turn_on
  - repeat:
      sequence:
        - data:
            hub: ELWA
            unit: 1
            address: 1000
            value: >
              {% set vxx = states('sensor.vxxout') | float(0) %} {{ vxx if vxx
              <= 3000 else 3000 }}
          action: modbus.write_register
        - delay: "00:00:05"
      until:
        - condition: template
          value_template: "{{ states('sensor.vxxout') | float <= 800 }}"
  - target:
      entity_id: input_boolean.elwaupdate_running
    action: input_boolean.turn_off
mode: queued

Sensor VXXOUT is my export sensor.

P.S. So long it works perfect and with 0 errors.
P.S.2 The time outs…I try a lot of changes…looks as it is now, is working correct.
P.S.3 The bootlean is only to check if it runs the automation…to avoid double runs…

input_boolean:
  elwaupdate_running:
    name: ElwaUpdate Running
    initial: off

I have also this automation to run when thre is no solar power… night times or bad weather

alias: ELWA Start From 40 Until 60°C
description: Start ELWA when water temp is below 40°C and keep heating until 60°C
triggers:
  - entity_id: sensor.vxxout
    below: 1
    trigger: numeric_state
  - minutes: /5
    trigger: time_pattern
conditions:
  - condition: numeric_state
    entity_id: sensor.vxxout
    below: 1
  - condition: numeric_state
    entity_id: sensor.elwaxx_temp
    below: 40
actions:
  - repeat:
      until:
        - condition: numeric_state
          entity_id: sensor.elwaxx_temp
          above: 59.9
      sequence:
        - data:
            hub: ELWA
            unit: 1
            address: 1000
            value: 2000
          action: modbus.write_register
        - delay: "00:00:05"
mode: single

Thank you very Much!
After your great Interrupt i redesignt my last updated Blueprint and editet it!
Works Flawlessly
Geat IDEA!
Also editet my post from MARCH 8. 2026 - SO this is my (today :wink: ) latest functioning Version

PS - Time is always a rare Value … so take yours! :wink:

So here is one clean and nice Elwa setup.

What is doing?

When solar kick inn heat with surplus when no solar goes on Backup mode and heat with grid till set temp of the automation ( Temperatures can setup as you like inside the automation). I have test it and runs very nice on my system also on a system of a friend.

So here is step by step how.

  1. Make a bootlean

  2. Settings

  3. Devices & Services

  4. Helpers

  5. Click Create Helper

  6. Choose → Toggle (Input Boolean)

  7. Name it:

    • ELWA Heating Active

Add this automations:

Automation 1

alias: ELWA Keepalive
description: Sends ELWA power every 7s (solar + backup, timeout-safe)

trigger:
  - platform: time_pattern
    seconds: "/7"

mode: restart

condition:
  - condition: state
    entity_id: input_boolean.elwa_heating_active
    state: "on"

action:
  - variables:
      surplus: "{{ states('sensor.vxxout') | float(0) }}"

      solar_min: 800
      solar_cap: 2000
      solar_factor: 0.9

      solar_power: "{{ [surplus * solar_factor, solar_cap] | min | int }}"

  - choose:

      # SOLAR MODE
      - conditions:
          - condition: template
            value_template: "{{ surplus >= solar_min }}"
        sequence:
          - service: modbus.write_register
            data:
              hub: ELWA
              unit: 1
              address: 1000
              value: "{{ solar_power }}"

    default:

      # BACKUP MODE (NO SOLAR)
      - service: modbus.write_register
        data:
          hub: ELWA
          unit: 1
          address: 1000
          value: 2000

Automation 2

alias: ElwaUpdate
description: ELWA heating permission controller (solar + backup split)

trigger:
  - platform: state
    entity_id:
      - sensor.YOUR EXPORT SENSOR
      - sensor.elwa_temp
  - platform: time_pattern
    minutes: "/5"

mode: restart

action:
  - variables:
      temp: "{{ states('sensor.elwaxx_temp') | float(0) }}"
      surplus: "{{ states('sensor.YOUR EXPORT SENSOR') | float(0) }}"
      solar_min: 800

  - choose:

      # HARD STOP (safety)
      - conditions:
          - condition: template
            value_template: "{{ temp >= 70 }}"
        sequence:
          - service: input_boolean.turn_off
            target:
              entity_id: input_boolean.elwa_heating_active

      # BACKUP MODE (NO SOLAR, COLD TANK)
      - conditions:
          - condition: template
            value_template: "{{ temp < 40 and surplus < solar_min }}"
        sequence:
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.elwa_heating_active

      # SOLAR MODE (NORMAL OPERATION)
      - conditions:
          - condition: template
            value_template: "{{ temp < 70 and surplus >= solar_min }}"
        sequence:
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.elwa_heating_active

    default:
      - service: input_boolean.turn_off
        target:
          entity_id: input_boolean.elwa_heating_active


Please notice this working with MODBUS TCP setup.

Enjoy