Atlantic Aurea hybrid heatpump controller

Herewith I share my implementation for the Atlantic Aurea hybride heatpump. Feedback and suggestions are welcome!

Atlantic Aurea is a hybride heatpump that switches between traditional gas a and heatpump heating. It comes with the Plugwise Smile Opentherm module and a Plugwise Anna thermostat. (see Aurea Hybride add-on - Atlantic Therefore, it can be integrated in Home Assistant using the Plugwise integration.

Unfortunately, there is no direct way to set it to gas or heatpump operation. I experimented with some parameters to influence this. I use an automation that manipulates the Anna thermostat between certain limits to ‘force’ the heatpump mode instead of gas where possible. As long as the outside temperature is higher than 4.5 degrees, it keeps the heatpump running when there is a heat request.

The Anna thermostat is only used to controll the Atlantic aurea, and is in my case located near the gas heater. Instead I use zwave radiator thermostats, so the user can set the temperature there, but couls also be done using a seperate wall thermostat that sets the input helper.

I use multiple temperature sensors in the house and an input_number helper that can be set to enter the desired temperature per room. finally I calculate the difference between de desired temperature and the measured average temperature. This is called the temperature_request.


front end for the users

Settings front end


Stuff for the nerd

Code below is my package (see Packages - Home Assistant) that defines both helpers and the automation.

it defines these entities:

entity description
input_number.heatpump_setpoint temperature that the controller wil set the Anna to in order to manipulate it
input_number.temperature_target desired home temperature
sensor.temperature_avg Average temperature for a room when multiple temperature sensors are used
sensor.temperature_req_generic ultimate heat request from all rooms
sensor.temperature_req calculated hear request (difference between measured and requested temperature)
sensor.heatpump_status indicator if the heatpump is in heatpump or hybrid mode
sensor.delta_water_heat actual amount of degrees the unit feeds into the house
sensor.delta_setpoint difference between actual Anna setpoint and anna temperature
sensor.heating_capacity Percesntage heating power used, for both gas or electric
sensor.heatpump_capacity percentage power used for heatpump only (based on electricity usage measurement)
binary_sensor.heatpump_active indicating if the heatpump is on

Note: the capacity of the heatpump is measured using a power plug meter the heatpump is connected to. (in my case sensor.heatpump_electric_consumption_w)

Additionally, it requires the following sensors:

sensor description
input_boolean.heatpump_force helper entity to enable or disabling the manipulation
sensor.smile_anna_outdoor_temperature provded by Plugwise Anna thermostat
sensor.opentherm_modulation_level provded through Plugwise Smile by you gas heater using OpenTherm
sensor.opentherm_water_temperature provded through Plugwise Smile by you gas heater using OpenTherm
sensor.opentherm_intended_boiler_temperature provded by Plugwise Smile
sensor.opentherm_return_temperature provded through Plugwise Smile by you gas heater using OpenTherm
binary_sensor.opentherm_tap_water provded through Plugwise Smile by you gas heater using OpenTherm
climate.anna provded by Plugwise Anna thermostat

The Package

heatpump_controler_automation:

# -- COMPONENTS --
# specific components are defined here

  input_number:
    heatpump_setpoint:
      name: doeltemperatuur warmtepomp
      icon: mdi:thermometer
      unit_of_measurement: '°C'
      min: -10
      max: 55
      mode: box

    temperature_target:
      name: Thermostaat doeltemperatuur
      min: 10
      max: 28
      step: 0.5
      mode: box
      unit_of_measurement: '°C'
      icon: mdi:home-thermometer-outline

  sensor:
  - unique_id: S9875243095876324
    name: temperature_avg
    platform: min_max
    type: median
    round_digits: 1
    entity_ids:
      - sensor.temperature_1 
      - sensor.temperature_2 
      - sensor.temperature_3 

  - unique_id: B003874B41197742D5AC2D1552F5630B0
    name: temperature_req_generic
    unit_of_measurement: '°C'
    platform: group
    type: max
    entities:
      - sensor.temperature_req
   #  - sensor.temperature_req_living
   #  - sensor.temperature_req_office


  template:
    - unique_id: C09323445876
      sensor:
      - name: "temperature_req"
        icon: mdi:thermometer-plus
        device_class: temperature
        unit_of_measurement: '°C'
        state: >
          {%- set raw_req=(states("input_number.temperature_target") | float(0) - states("sensor.temperature_avg") | float(0)) | round(1)-%}
          {%- if raw_req > 0 -%}{{raw_req}}{%- else -%}0{%- endif -%}


    - sensor:
        unique_id: 01618CE9-A658-4140-87C5-7B597B9BC13C
        name: heatpump_status
        icon: mdi:heat-pump-outline
        state: >
          {% set current = this.state |default("", 1)%}
          {% if trigger.platform == 'state' or trigger.event.data.value is not defined %}
            {{ current }}
          {% else %}
            {{ trigger.event.data.value }}
          {% endif %}    
      trigger:
        - platform: event
          event_type: heatpump_status_value

    - sensor:
        unique_id: c127cd2a-3112-b574-32ab-92c6dd8a322a
        name: delta_water_heat
        icon: mdi:thermometer
        unit_of_measurement: '°C'
        state: >
            {% set delta= (states("sensor.opentherm_water_temperature") | float(0) - states("sensor.opentherm_return_temperature") | float(0)) | round(2) %}
            {%- if delta > 0-%}
              {%- if delta < 30-%}{{ delta }}
              {%- else -%} 30 {%- endif -%}
            {%- else -%} 0 {%- endif -%}

    - sensor:
        unique_id: c234ab1b-3112-b574-32ab-92c6aaba88311b
        name: delta_setpoint
        icon: mdi:thermometer
        unit_of_measurement: '°C'
        state: >
          {{ (states("sensor.anna_setpoint") | float(0) - states("sensor.anna_temperature") | float(0)) | round(2) }}
      
    - sensor:
        unique_id: c321122a-127cd-b574-32ab-92c6dd8b113
        name: heating_capacity
        unit_of_measurement: '%'
        state: >
          {% if states("sensor.opentherm_modulation_level") | float(0) > 0 %}
            {{ states("sensor.opentherm_modulation_level") | float(0) }}
          {%- else -%}
            {% set cap = (((states('sensor.heatpump_electric_consumption_w') | float(0) - 12 ) / 2500 ) * 100) | float(0) | round(1) %}
            {% if cap < 0 -%}{% set cap = 0 %}{%- endif %}{{ cap | float(0) }}
          {%- endif %}  

    - sensor:
        unique_id: A321122a-127cd-b574-32ab-92c6dd8b111
        name: heatpump_capacity
        unit_of_measurement: '%'
        state: >
            {% set cap = ((states('sensor.heatpump_electric_consumption_w') | float(0) - 12 ) / 25) | float(0) | round(1) %}
            {% if cap < 0 -%}{% set cap = 0 %}{%- endif %}{{ cap | float(0) }}

    - binary_sensor:
        unique_id: bb2bcf8e-692b-4cbe-b1ee-7c60a87b212
        name: heatpump_active
        icon: mdi:heat-pump-outline
        state: >
          {{ ((states('sensor.heatpump_electric_consumption_w') | float(0) - 12 ) / 25) | float(0) | round(0) > 10 }}

# -- AUTOMATIONS --
# actual magic happens here

  automation:
  # -- Heatpump Controler --
  - id: '1663864767086'
    alias: Heatpump Controler
    mode: restart

    variables:
      setpoint_max: 30
      water_temp_max: 52
      water_temp_delta_max: 8
    
    trigger:
    - platform: state
      entity_id:
      - sensor.temperature_req_generic
      - sensor.opentherm_modulation_level
      - sensor.opentherm_intended_boiler_temperature
      - sensor.heatpump_capacity
      for: '00:00:10'

    action:
      
    # No heat request
    - if:
        - condition: template
          value_template: '{{ states("sensor.temperature_req_generic") |float(0) <= 0 }}'
      then:
          - condition: template
            value_template: '{{ states("input_number.heatpump_setpoint") |float(0) >= 0 }}'
          - service: input_number.set_value
            data:
              value: -1
            target:
              entity_id: input_number.heatpump_setpoint

    # Heat request (Heatpump or Gas)
      else: 

        - if:
            # Heatpump only mode (when outside temp > 4.5)
            - condition: state
              entity_id: input_boolean.heatpump_force
              state: 'on'
            - condition: template
              value_template: >-
                {{ 
                  states("sensor.smile_anna_outdoor_temperature") |float(0) > 4.5
                }}
          then:
            # Gas heating is on, try to stop it            
            - if:
                - condition: template
                  value_template: >
                    {{ 
                      states("binary_sensor.opentherm_tap_water") == "off"
                      and states("sensor.opentherm_modulation_level") |float(0) > 0 
                      and states("sensor.opentherm_return_temperature") |float(0) > 35 
                    }}
              then:
                - service: input_number.set_value
                  target:
                    entity_id: input_number.heatpump_setpoint
                  data:
                    value: -1

             # Heatpump control
              else:
                - if:
                    # throttle to 0 to keep heatpump active
                    - condition: template
                      value_template: >
                        {% set boiler_temp = states("sensor.opentherm_intended_boiler_temperature") | float(0) %}
                        {% set water_temp = states("sensor.opentherm_water_temperature") | float(0) %}
                        {% set heatpump_capacity = states("sensor.heatpump_capacity") | float(0) %}
                        {{ (boiler_temp - water_temp > water_temp_delta_max | float(0)) or (heatpump_capacity > 80) }}
                  then:
                    - service: input_number.set_value
                      target:
                        entity_id: input_number.heatpump_setpoint
                      data:
                        value:  0
                  else:
                    - if:
                      # ease on when we have a large gap because it tends to switch to Gas
                      - condition: template
                        value_template: >
                          {{ (states("sensor.opentherm_intended_boiler_temperature") | float(0) - states("sensor.opentherm_water_temperature") | float(0)) | abs   > 4.5 }}
                      then:
                        - service: input_number.set_value
                          target:
                            entity_id: input_number.heatpump_setpoint
                          data:
                            value: 0.1

                      # nu issues, just set the setpoint for faster heating
                      else:
                        - service: input_number.set_value
                          target:
                            entity_id: input_number.heatpump_setpoint
                          data:
                            value: '{{ states("sensor.temperature_req_generic") |float(0)}}'

          # Don't care about the heatpump, just set the setpoint
          else:               

            - service: input_number.set_value
              target:
                entity_id: input_number.heatpump_setpoint
              data:
                value: '{{ states("sensor.temperature_req_generic") |float(0)}}'

    # Status update
    - event: heatpump_status_value
      event_data:
        value: >-
            {% if is_state("binary_sensor.heatpump_active", "on") %}
            Warmtepomp
            {% elif states("sensor.heating_capacity") | int(0) > 0 %}
            Hybride
            {% else %}
            Inactief
            {% endif %}
    
    # Max setpoint regulation
    - if:
      - condition: template
        value_template: >-
          {{ (state_attr("climate.anna","current_temperature") |float(0) + states("input_number.heatpump_setpoint") |float(0)) 
          > setpoint_max |float(0) }}
      then:
      - service: input_number.set_value
        data:
          value: '{{ setpoint_max |float(0) - state_attr("climate.anna","current_temperature") |float(0) }}'
        target:
          entity_id: input_number.heatpump_setpoint


    # Heatpump Controler: Apply Setpoint (if it is not set yet)
    - if:
      - condition: template
        value_template: >-
          {{ state_attr("climate.anna","temperature") |float(0) |round(1) != (state_attr("climate.anna","current_temperature") |float(0) + states("input_number.heatpump_setpoint") |float(0)) |round(1) }}
      then:
      - service: climate.set_temperature
        data:
          temperature: '{{ state_attr("climate.anna","current_temperature") |float(0) + states("input_number.heatpump_setpoint") |float(0) |round(1) }}'
          #target_temp_high: 30
          #target_temp_low: 10
        target:
          entity_id: climate.anna
      - service: logbook.log
        data:
          name: Verwarming
          message: >-
            TEMP SET ( {{ state_attr("climate.anna","current_temperature") |float(0) + states("input_number.heatpump_setpoint") |float(0) |round(1) }}°C ->
            {{ state_attr("climate.anna","temperature") |float(0) }} / 
            {{ state_attr("climate.anna","current_temperature") |float(0) }}°C )
1 Like

Hi @pdwonline

I am one of the integration-owners of the Plugwise integration.
You write that some control is missing.
That could very well be true because we rely on other Plugwise device owners to provide us with information that will help use add more functionality.

If anything is missing in Home Assistant, but is available in the Plugwise App please let me know!

Thanks for that!
Although I do use the Plugwise integration, it is not missing anything. The issue is that Plugwise comes bundled with the Aurea. It is connected to the Aurea controller using OpenTherm. So it is not Plugwise causing limitations to the Aurea, but the Aurea controller itself.

There is no OpenTherm command to switch between gas or Heat-pump. So i figured out within what conditions the Aurea keeps running using Heat-pump and my script keeps it within that range. One thing cannot be controlled: the Aurea has a hardware temperature sensor. When it comes below 4.5 degrees Celsius, the Aurea controller will switch to gas. I tried fooling the Aurea controller with an external temperature, but was not successful with that so far. I simply not like others deciding for me if I should heat my home using electricity or gas. Although the Aurea was pretty cheap, I whish I had known this on beforehand, probably I would have decided to pay some extra for e heat-pump that still operates at -5 degrees

1 Like

Ok, I understand what you want to achieve. And I read that you have created a multi-zone heating system with a single-room thermostat, nice job :slight_smile:

However, do you understand why at a temperatures below 4.5 degrees the system switches to heating from gas? At these temperatures the electrical consumption of the heatpump becomes so high that heating via gas is cheaper.

Let me decide myself what is cheaper; electricity from my solar panel or windmill or gas…

2 Likes

Thanks for this great initiative!
I recently bought this heat pump 2nd hand with the Plugwise Anna. The heat pump itself is nice and the control box looks old-fashioned but decently made. However, the software in that box is an absolute disaster. Really old fashioned (early zero’s tech) and nothing to adjust and no possibility to upgrade firmware (Atmel8L microcontroller are used).
So, very happy with your work and looking out to using it. However, I only can’t get it to work…
I have have the code as a yaml file and placed in a ‘packages’ sub folder of the config folder.
I also added ‘packages: !include_dir_named packages’ under home assistant in the config.yaml.
When I check the configuration it comes back as valid, however, I get also the error code:
Setup of package ‘heatpump_controler_automation’ failed: Integration ‘heatpump_controler_automation’ not found.

It is probably something simple I not to do, but I can’t find it out.

try : packages: !include_dir_merge_named packages

Thanks! I have been able to load the package. Now I am trying to adapt your situation for mine (e.g. power measurement, sensors etc.).

PS: You mentioned that you want to have control over the outside temperature where the heatpump stops. In this topic Basisregeling van de Aurea 5 hybrid add-on - Duurzame energie en installaties - GoT. It’s in Dutch, but that’s no problem for you I think :wink:
People have been manipulating the outside sensor on the heatpump in various ways.

1 Like

@pdwonline Dank… ik ben al redelijk ver met mijn setup… Alleen mijn Plugwise Anna is in het Nederlands. Ideaal is deze ook engels zodat ik zeker weet alles goed over te zetten/ ik de package volledig kan kopiëren. (Alleen blijft deze natuurlijk persoonlijk: in my case sensor.heatpump_electric_consumption_w) Ik heb Anna/Plugwise opnieuw geinstalleerd en via app op Engels gezet alleen deze blijft engels… Hier nog een tip voor?

Ik heb nu onderstaande: resultaat is nadat ik de helper aanzet ik alleen nog de CV laat aanslaag en niet meer de WP… :wink: Nu wil ik ook mijn package delen in een mooi window… maar zelfs dat lukt niet… OMG… dan maar zo, excuses///

# packages/heatpump_controler_automation.yaml
# GEEN bovenliggende sleutel gebruiken; direct top-level domeinen.

template:
  # Kamertemperatuur uit Anna
  - sensor:
      - unique_id: bastiaan_temp_avg
        name: temperature_avg
        icon: mdi:thermometer
        device_class: temperature
        unit_of_measurement: "°C"
        state: "{{ states('sensor.anna_temperatuur') | float(0) | round(1) }}"

  # Warmtevraag (max(0, target - gemeten))
  - unique_id: bastiaan_temp_req
    sensor:
      - name: "temperature_req"
        icon: mdi:thermometer-plus
        device_class: temperature
        unit_of_measurement: "°C"
        state: >
          {% set raw_req = (states('input_number.temperature_target') | float(0)
                            - states('sensor.temperature_avg') | float(0)) | round(1) %}
          {{ raw_req if raw_req > 0 else 0 }}

  # In 1-kamer setup is 'generic' gelijk aan 'temperature_req'
  - sensor:
      unique_id: bastiaan_temp_req_generic
      name: temperature_req_generic
      icon: mdi:thermometer-plus
      device_class: temperature
      unit_of_measurement: "°C"
      state: "{{ states('sensor.temperature_req') }}"

  # Status event-sensor
  - sensor:
      unique_id: bastiaan_heatpump_status
      name: heatpump_status
      icon: mdi:heat-pump-outline
      state: >
        {% set current = this.state | default('', true) %}
        {% if trigger.platform == 'state' or trigger.event.data.value is not defined %}
          {{ current }}
        {% else %}
          {{ trigger.event.data.value }}
        {% endif %}
    trigger:
      - platform: event
        event_type: heatpump_status_value

  # Delta water ↔ retour (max 30°C)
  - sensor:
      unique_id: bastiaan_delta_water_heat
      name: delta_water_heat
      icon: mdi:thermometer
      unit_of_measurement: "°C"
      state: >
        {% set delta = (states('sensor.opentherm_watertemperatuur') | float(0)
                        - states('sensor.opentherm_retourtemperatuur') | float(0)) | round(2) %}
        {% if delta > 0 %}{{ 30 if delta > 30 else delta }}{% else %}0{% endif %}

  # Verwarmingscapaciteit (gasmodulatie of fallback Shelly)
  - sensor:
      unique_id: bastiaan_heating_capacity
      name: heating_capacity
      unit_of_measurement: "%"
      state: >
        {% if states('sensor.opentherm_modulatieniveau') | float(0) > 0 %}
          {{ states('sensor.opentherm_modulatieniveau') | float(0) }}
        {% else %}
          {% set cap = (((states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12) / 2500) * 100) | round(1) %}
          {{ 0 if cap < 0 else cap }}
        {% endif %}

  # Warmtepomp-capaciteit uit elektrisch verbruik
  - sensor:
      unique_id: bastiaan_heatpump_capacity
      name: heatpump_capacity
      unit_of_measurement: "%"
      state: >
        {% set cap = ((states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12) / 25) | round(1) %}
        {{ 0 if cap < 0 else cap }}

  # Binaire status warmtepomp
  - binary_sensor:
      unique_id: bastiaan_heatpump_active
      name: heatpump_active
      icon: mdi:heat-pump-outline
      state: >
        {{ (((states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12) / 25) | round(0)) > 10 }}

automation:
  - id: "1663864767086"
    alias: Heatpump Controller
    mode: restart

    variables:
      setpoint_max: 30
      water_temp_max: 52
      water_temp_delta_max: 8

    trigger:
      - platform: state
        entity_id:
          - sensor.temperature_req
          - sensor.opentherm_modulatieniveau
          - sensor.opentherm_beoogde_keteltemperatuur
          - sensor.heatpump_capacity
        for: "00:00:10"

    action:
      # Geen warmtevraag
      - if:
          - condition: template
            value_template: "{{ states('sensor.temperature_req') | float(0) <= 0 }}"
        then:
          - condition: template
            value_template: "{{ states('input_number.heatpump_setpoint') | float(0) >= 0 }}"
          - service: input_number.set_value
            target:
              entity_id: input_number.heatpump_setpoint
            data:
              value: -1

        else:
          # Alleen warmtepomp als buiten > 4.5°C én force aan
          - if:
              - condition: state
                entity_id: input_boolean.heatpump_force
                state: "on"
              - condition: template
                value_template: "{{ states('sensor.smile_anna_buitentemperatuur') | float(0) > 4.5 }}"
            then:
              # Gas actief? probeer te stoppen
              - if:
                  - condition: template
                    value_template: >
                      {{
                        states('binary_sensor.opentherm_sww_status') == 'off'
                        and states('sensor.opentherm_modulatieniveau') | float(0) > 0
                        and states('sensor.opentherm_retourtemperatuur') | float(0) > 35
                      }}
                then:
                  - service: input_number.set_value
                    target:
                      entity_id: input_number.heatpump_setpoint
                    data:
                      value: -1

                else:
                  # Warmtepompregeling
                  - if:
                      - condition: template
                        value_template: >
                          {% set boiler_temp = states('sensor.opentherm_beoogde_keteltemperatuur') | float(0) %}
                          {% set water_temp = states('sensor.opentherm_watertemperatuur') | float(0) %}
                          {% set hp_cap = states('sensor.heatpump_capacity') | float(0) %}
                          {{ (boiler_temp - water_temp > water_temp_delta_max | float(0)) or (hp_cap > 80) }}
                    then:
                      - service: input_number.set_value
                        target:
                          entity_id: input_number.heatpump_setpoint
                        data:
                          value: 0
                    else:
                      - if:
                          - condition: template
                            value_template: >
                              {{ (states('sensor.opentherm_beoogde_keteltemperatuur') | float(0)
                                  - states('sensor.opentherm_watertemperatuur') | float(0)) | abs > 4.5 }}
                        then:
                          - service: input_number.set_value
                            target:
                              entity_id: input_number.heatpump_setpoint
                            data:
                              value: 0.1
                        else:
                          - service: input_number.set_value
                            target:
                              entity_id: input_number.heatpump_setpoint
                            data:
                              value: "{{ states('sensor.temperature_req') | float(0) }}"
            else:
              # Hybride/gasmodus
              - service: input_number.set_value
                target:
                  entity_id: input_number.heatpump_setpoint
                data:
                  value: "{{ states('sensor.temperature_req') | float(0) }}"

      # Status-update
      - event: heatpump_status_value
        event_data:
          value: >
            {% if is_state('binary_sensor.heatpump_active', 'on') %}
            Warmtepomp
            {% elif states('sensor.heating_capacity') | int(0) > 0 %}
            Hybride
            {% else %}
            Inactief
            {% endif %}

      # Max setpoint beperken
      - if:
          - condition: template
            value_template: >
              {{ (states('sensor.anna_temperatuur') | float(0)
                  + states('input_number.heatpump_setpoint') | float(0))
                 > setpoint_max | float(0) }}
        then:
          - service: input_number.set_value
            target:
              entity_id: input_number.heatpump_setpoint
            data:
              value: >
                {{ setpoint_max | float(0) - states('sensor.anna_temperatuur') | float(0) }}

      # Nieuw setpoint naar thermostaat
      - if:
          - condition: template
            value_template: >
              {{ (states('sensor.anna_instelpunt') | float(0)) | round(1)
                 != (states('sensor.anna_temperatuur') | float(0)
                     + states('input_number.heatpump_setpoint') | float(0)) | round(1) }}
        then:
          - service: climate.set_temperature
            target:
              entity_id: climate.anna
            data:
              temperature: >
                {{ (states('sensor.anna_temperatuur') | float(0)
                    + states('input_number.heatpump_setpoint') | float(0)) | round(1) }}
          - service: logbook.log
            data:
              name: Verwarming
              message: >
                TEMP SET ( {{ (states('sensor.anna_temperatuur') | float(0)
                  + states('input_number.heatpump_setpoint') | float(0)) | round(1) }}°C ->
                {{ states('sensor.anna_instelpunt') | float(0) }} /
                {{ states('sensor.anna_temperatuur') | float(0) }}°C )

@bgover Ik begrijo jouw vraag niet helemaal, Nadat je de helper aanzet: wat bedoel je daarmee. Controleer of je alle sensors hebt: sensor.temperature_avg, temperature_req, de opentherm sensors.

Iets duidelijker: wat gaat goed en wat gaat mis. Geef anders ff een lijstje van jouw sensornamen

1 Like

@pdwonline Excuses vraag was/is onduidelijk. Wat er gebeurde: temperatuur via helper Thermostaat doeltemperatuur
aanpassen lukte alleen wanneer via de HEATPUMP FORCE knop uit stond. Wanneer ik die aanzette reageerde Slave/Anna niet mee. Dat was op een gegeven moment opgelost. Toen had ik na veel aanpassingen een werkend systeem behalve dat warmtepomp niet meer uitgaat. Hij bleef er steeds een tiende bijgooien. Dit zijn mijn entiteiten:

| Categorie                                                      | Omschrijving                                    | Entity ID        | Type / Plugin |
| -------------------------------------------------------------- | ----------------------------------------------- | ---------------- | ------------- |
| **Helpers & Custom Sensors**                                   |                                                 |                  |               |
| Doeltemperatuur warmtepomp (interne offset)                    | `input_number.heatpump_setpoint`                | Numerieke invoer |               |
| Heatpump force (handmatige aansturing)                         | `input_boolean.heatpump_force`                  | Boolean invoer   |               |
| Thermostaat doeltemperatuur (gewenst setpoint)                 | `input_number.temperature_target`               | Numerieke invoer |               |
| Kamertemperatuur uit Anna                                      | `sensor.temperature_avg`                        | Template         |               |
| Warmtevraag (verschil target - gemeten)                        | `sensor.temperature_req`                        | Template         |               |
| Warmtevraag (generiek, 1-zone)                                 | `sensor.temperature_req_generic`                | Template         |               |
| Verwarmingscapaciteit (OpenTherm of Shelly fallback)           | `sensor.heating_capacity`                       | Template         |               |
| Warmtepomp actief (binaire status)                             | `binary_sensor.heatpump_active`                 | Template         |               |
| Warmtepomp vermogen (%)                                        | `sensor.heatpump_capacity`                      | Template         |               |
| Status warmtepomp (tekstueel: inactief / hybride / warmtepomp) | `sensor.heatpump_status`                        | Template         |               |
| Delta water ↔ retourtemperatuur                                | `sensor.delta_water_heat`                       | Template         |               |
| Test sensor (optioneel)                                        | `sensor.test_sensor`                            | Template         |               |
| Vermogen Shelly warmtepomp                                     | `sensor.shellypro1pm_ec62608c06a8_power`        | Shelly Pro 1PM   |               |
| **OpenTherm**                                                  |                                                 |                  |               |
| Beoogde keteltemperatuur                                       | `sensor.opentherm_beoogde_keteltemperatuur`     | Plugwise         |               |
| Instelpunt warm water                                          | `number.opentherm_instelpunt_warm_water`        | Plugwise         |               |
| Modulatieniveau                                                | `sensor.opentherm_modulatieniveau`              | Plugwise         |               |
| Retourtemperatuur                                              | `sensor.opentherm_retourtemperatuur`            | Plugwise         |               |
| SWW comfort modus                                              | `switch.opentherm_sww_comfort_modus`            | Plugwise         |               |
| SWW status                                                     | `binary_sensor.opentherm_sww_status`            | Plugwise         |               |
| Verwarmen actief                                               | `binary_sensor.opentherm_verwarmen`             | Plugwise         |               |
| Vlamstatus                                                     | `binary_sensor.opentherm_vlam_status`           | Plugwise         |               |
| Waterdruk                                                      | `sensor.opentherm_waterdruk`                    | Plugwise         |               |
| Watertemperatuur (aanvoer)                                     | `sensor.opentherm_watertemperatuur`             | Plugwise         |               |
| **Anna (thermostaat)**                                         |                                                 |                  |               |
| Klimaat-entiteit                                               | `climate.anna`                                  | Plugwise         |               |
| Instelpunt (doeltemperatuur van Anna)                          | `sensor.anna_instelpunt`                        | Plugwise         |               |
| Temperatuur (kamer)                                            | `sensor.anna_temperatuur`                       | Plugwise         |               |
| Temperatuurcompensatie                                         | `number.anna_temperatuurcompensatie`            | Plugwise         |               |
| Licht (weergave in thermostaat)                                | `sensor.anna_licht`                             | Plugwise         |               |
| Schema-selectie                                                | `select.anna_thermostaat_schema`                | Plugwise         |               |
| **Smile Anna (gateway)**                                       |                                                 |                  |               |
| Buitentemperatuur                                              | `sensor.smile_anna_buitentemperatuur`           | Plugwise         |               |
| Herstartknop                                                   | `button.smile_anna_herstarten`                  | Plugwise         |               |
| Notificatie (status Plugwise gateway)                          | `binary_sensor.smile_anna_plugwise_notificatie` | Plugwise         |               |

Dit was het script dat maar bleef verwarmen: (ChatGPT sprak van: steeds een duwtje van 0,1 erbij)

# packages/heatpump_controler_automation.yaml
# GEEN bovenliggende sleutel gebruiken; direct top-level domeinen.

template:
  # Kamertemperatuur uit Anna
  - sensor:
      - unique_id: bastiaan_temp_avg
        name: temperature_avg
        icon: mdi:thermometer
        device_class: temperature
        unit_of_measurement: "°C"
        state: "{{ states('sensor.anna_temperatuur') | float(0) | round(1) }}"

  # Warmtevraag (max(0, target - gemeten))
  - unique_id: bastiaan_temp_req
    sensor:
      - name: "temperature_req"
        icon: mdi:thermometer-plus
        device_class: temperature
        unit_of_measurement: "°C"
        state: >
          {% set raw_req = (states('input_number.temperature_target') | float(0)
                            - states('sensor.temperature_avg') | float(0)) | round(1) %}
          {{ raw_req if raw_req > 0 else 0 }}

  # In 1-kamer setup is 'generic' gelijk aan 'temperature_req'
  - sensor:
      unique_id: bastiaan_temp_req_generic
      name: temperature_req_generic
      icon: mdi:thermometer-plus
      device_class: temperature
      unit_of_measurement: "°C"
      state: "{{ states('sensor.temperature_req') }}"

  # Status event-sensor
  - sensor:
      unique_id: bastiaan_heatpump_status
      name: heatpump_status
      icon: mdi:heat-pump-outline
      state: >
        {% set current = this.state | default('', true) %}
        {% if trigger.platform == 'state' or trigger.event.data.value is not defined %}
          {{ current }}
        {% else %}
          {{ trigger.event.data.value }}
        {% endif %}
    trigger:
      - platform: event
        event_type: heatpump_status_value

  # Delta water ↔ retour (max 30°C)
  - sensor:
      unique_id: bastiaan_delta_water_heat
      name: delta_water_heat
      icon: mdi:thermometer
      unit_of_measurement: "°C"
      state: >
        {% set delta = (states('sensor.opentherm_watertemperatuur') | float(0)
                        - states('sensor.opentherm_retourtemperatuur') | float(0)) | round(2) %}
        {% if delta > 0 %}{{ 30 if delta > 30 else delta }}{% else %}0{% endif %}

  # Verwarmingscapaciteit (gasmodulatie of fallback Shelly)
  - sensor:
      unique_id: bastiaan_heating_capacity
      name: heating_capacity
      unit_of_measurement: "%"
      state: >
        {% if states('sensor.opentherm_modulatieniveau') | float(0) > 0 %}
          {{ states('sensor.opentherm_modulatieniveau') | float(0) }}
        {% else %}
          {% set cap = (((states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12) / 2500) * 100) | round(1) %}
          {{ 0 if cap < 0 else cap }}
        {% endif %}

  # Warmtepomp-capaciteit uit elektrisch verbruik
  - sensor:
      unique_id: bastiaan_heatpump_capacity
      name: heatpump_capacity
      unit_of_measurement: "%"
      state: >
        {% set cap = ((states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12) / 25) | round(1) %}
        {{ 0 if cap < 0 else cap }}

  # Binaire status warmtepomp
  - binary_sensor:
      unique_id: bastiaan_heatpump_active
      name: heatpump_active
      icon: mdi:heat-pump-outline
      state: >
        {{ (((states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12) / 25) | round(0)) > 10 }}

automation:
  - id: "1663864767086"
    alias: Heatpump Controller
    mode: restart

    variables:
      setpoint_max: 30
      water_temp_max: 52
      water_temp_delta_max: 8

    trigger:
      - platform: state
        entity_id:
          - sensor.temperature_req
          - sensor.opentherm_modulatieniveau
          - sensor.opentherm_beoogde_keteltemperatuur
          - sensor.heatpump_capacity
        for: "00:00:10"

      - platform: state
        entity_id: input_boolean.heatpump_force

      - platform: state
        entity_id: sensor.smile_anna_buitentemperatuur
        for: "00:00:10"
        
      - platform: state
        entity_id: input_number.temperature_target
  
    action:
      # Geen warmtevraag
      - if:
          - condition: template
            value_template: "{{ states('sensor.temperature_req') | float(0) <= 0 }}"
        then:
          - condition: template
            value_template: "{{ states('input_number.heatpump_setpoint') | float(0) >= 0 }}"
          - service: input_number.set_value
            target:
              entity_id: input_number.heatpump_setpoint
            data:
              value: 0

        else:
          # FORCE-pad (alleen bij force=on én buiten > 4.5 °C)
          - if:
              - condition: state
                entity_id: input_boolean.heatpump_force
                state: "on"
              - condition: template
                value_template: "{{ states('sensor.smile_anna_buitentemperatuur') | float(0) > 4.5 }}"
            then:
              # Gas actief? zacht stoppen (niet naar -1, anders wordt Anna inactief)
              - if:
                  - condition: template
                    value_template: >
                      {{
                        states('binary_sensor.opentherm_sww_status') == 'off'
                        and states('sensor.opentherm_modulatieniveau') | float(0) > 0
                        and states('sensor.opentherm_retourtemperatuur') | float(0) > 35
                      }}
                then:
                  - service: input_number.set_value
                    target: { entity_id: input_number.heatpump_setpoint }
                    data: "{{ states('sensor.temperature_req') | float(0) }}"
                else:
                  - if:
                      - condition: template
                        value_template: >
                          {% set boiler_temp = states('sensor.opentherm_beoogde_keteltemperatuur') | float(0) %}
                          {% set water_temp  = states('sensor.opentherm_watertemperatuur') | float(0) %}
                          {% set hp_cap      = states('sensor.heatpump_capacity') | float(0) %}
                          {{ (boiler_temp - water_temp > water_temp_delta_max | float(0)) or (hp_cap > 80) }}
                    then:
                      - service: input_number.set_value
                        target: { entity_id: input_number.heatpump_setpoint }
                        data: "{{ states('sensor.temperature_req') | float(0) }}"
                    else:
                      - if:
                          - condition: template
                            value_template: >
                              {{
                                (states('sensor.opentherm_beoogde_keteltemperatuur') | float(0)
                                - states('sensor.opentherm_watertemperatuur')        | float(0)) | abs > 4.5
                              }}
                        then:
                          - service: input_number.set_value
                            target: { entity_id: input_number.heatpump_setpoint }
                            data: { value: 0.1 }
                        else:
                          - service: input_number.set_value
                            target: { entity_id: input_number.heatpump_setpoint }
                            data:
                              value: "{{ states('sensor.temperature_req') | float(0) }}"

            else:
              # Hybride/gasmodus
              - service: input_number.set_value
                target: { entity_id: input_number.heatpump_setpoint }
                data:
                  value: "{{ states('sensor.temperature_req') | float(0) }}"

      # Status-update
      - event: heatpump_status_value
        event_data:
          value: >
            {% if is_state('binary_sensor.heatpump_active', 'on') %}Warmtepomp
            {% elif states('sensor.heating_capacity') | int(0) > 0 %}Hybride
            {% else %}Inactief{% endif %}

      # Max setpoint beperken
      - if:
          - condition: template
            value_template: >
              {{ (states('sensor.anna_temperatuur') | float(0)
                  + states('input_number.heatpump_setpoint') | float(0))
                 > setpoint_max | float(0) }}
        then:
          - service: input_number.set_value
            target: { entity_id: input_number.heatpump_setpoint }
            data:
              value: >
                {{ setpoint_max | float(0) - states('sensor.anna_temperatuur') | float(0) }}

      # Nieuw setpoint naar Anna
      - if:
          - condition: template
            value_template: >
              {{ (states('sensor.anna_instelpunt') | float(0)) | round(1)
                 != (states('sensor.anna_temperatuur') | float(0)
                     + states('input_number.heatpump_setpoint') | float(0)) | round(1) }}
        then:
          - service: climate.set_temperature
            target: { entity_id: climate.anna }
            data:
              temperature: >
                {{ (states('sensor.anna_temperatuur') | float(0)
                    + states('input_number.heatpump_setpoint') | float(0)) | round(1) }}
          - service: logbook.log
            data:
              name: Verwarming
              message: >
                TEMP SET ( {{ (states('sensor.anna_temperatuur') | float(0)
                  + states('input_number.heatpump_setpoint') | float(0)) | round(1) }}°C ->
                {{ states('sensor.anna_instelpunt') | float(0) }} /
                {{ states('sensor.anna_temperatuur') | float(0) }}°C )

Nu heb ik deze draaien alleen nu reageert de Anna/Slave niet meer via de helpers… en moet ik temp via Anna instellen alleen geen vertrouwen dat warmepomp blijft draaien als zo iets kouder wordt, dan CV dan weer steeds bijspringt…

# packages/heatpump_controller_automation.yaml
# VOLLEDIG AFGESTEMD OP JOUW ENTITEITEN – ZONDER {% set %} IN state:

template:

  # Kamertemperatuur uit Anna
  - sensor:
      - unique_id: bastiaan_temp_avg
        name: temperature_avg
        icon: mdi:thermometer
        device_class: temperature
        unit_of_measurement: "°C"
        state: "{{ states('sensor.anna_temperatuur') | float(0) | round(1) }}"

  # Warmtevraag met deadband 0.3 °C
  - sensor:
      - unique_id: bastiaan_temp_req
        name: temperature_req
        icon: mdi:thermometer-plus
        device_class: temperature
        unit_of_measurement: "°C"
        state: >
          {{ ( (states('input_number.temperature_target')|float(0)
               - states('sensor.temperature_avg')|float(0) - 0.3) )
             | float(0) | max(0) | round(2) }}

  # Generic (1-kamer)
  - sensor:
      - unique_id: bastiaan_temp_req_generic
        name: temperature_req_generic
        icon: mdi:thermometer-plus
        device_class: temperature
        unit_of_measurement: "°C"
        state: "{{ states('sensor.temperature_req') | float(0) }}"

  # Status event-sensor (trigger-template)
  - trigger:
      - platform: event
        event_type: heatpump_status_value
    sensor:
      - unique_id: bastiaan_heatpump_status
        name: heatpump_status
        icon: mdi:heat-pump-outline
        state: >
          {{ trigger.event.data.value if trigger and trigger.event and
             trigger.event.data and ('value' in trigger.event.data) else (this.state | default('')) }}

  # Delta water ↔ retour (0..30 °C)
  - sensor:
      - unique_id: bastiaan_delta_water_heat
        name: delta_water_heat
        icon: mdi:thermometer
        unit_of_measurement: "°C"
        state: >
          {% set d = (states('sensor.opentherm_watertemperatuur')|float(0)
                      - states('sensor.opentherm_retourtemperatuur')|float(0)) | round(2) %}
          {{ 0 if d <= 0 else (30 if d > 30 else d) }}

  # Verwarmingscapaciteit (OT of Shelly fallback)
  - sensor:
      - unique_id: bastiaan_heating_capacity
        name: heating_capacity
        unit_of_measurement: "%"
        state: >
          {{ (states('sensor.opentherm_modulatieniveau')|float(0))
             if (states('sensor.opentherm_modulatieniveau')|float(0)) > 0
             else ( (( (states('sensor.shellypro1pm_ec62608c06a8_power')|float(0) - 12 ) / 2500) * 100 ) | round(1) | max(0) ) }}

  # Warmtepomp-capaciteit uit elektrisch verbruik (>=0)
  - sensor:
      - unique_id: bastiaan_heatpump_capacity
        name: heatpump_capacity
        unit_of_measurement: "%"
        state: >
          {{ ( ((states('sensor.shellypro1pm_ec62608c06a8_power')|float(0) - 12) / 25) | round(1) ) | max(0) }}

  # Binaire status warmtepomp
  - binary_sensor:
      - unique_id: bastiaan_heatpump_active
        name: heatpump_active
        icon: mdi:heat-pump-outline
        state: >
          {{ ((((states('sensor.shellypro1pm_ec62608c06a8_power')|float(0) - 12) / 25) | round(0)) > 10) }}

automation:
  - id: heatpump_controller
    alias: Heatpump Controller
    initial_state: true
    mode: restart

    variables:
      setpoint_max: 30
      water_temp_delta_max: 8
      hysteresis: 0.3
      step_size: 0.5

    trigger:
      - platform: state
        entity_id:
          - sensor.temperature_req
          - input_boolean.heatpump_force
          - input_number.temperature_target
          - sensor.opentherm_modulatieniveau
          - sensor.opentherm_beoogde_keteltemperatuur
          - sensor.heatpump_capacity
        for: "00:00:10"

    action:
      # FAST-PATH: reageer direct op helper
      - variables:
          trig_entity: "{{ trigger.entity_id | default('') }}"
      - choose:
          - conditions: "{{ trig_entity == 'input_number.temperature_target' }}"
            sequence:
              - variables:
                  step: "{{ state_attr('climate.anna','target_temp_step') | float(0.5) }}"
                  v:    "{{ states('input_number.temperature_target') | float(0) }}"
                  target_direct: "{{ ((v / step) | round(0) * step) | round(1) }}"
                  anna_now_direct: "{{ state_attr('climate.anna','temperature') | float(0) }}"
                  anna_mode_direct: "{{ state_attr('climate.anna','hvac_mode') | default('heat') }}"
              - choose:
                  - conditions: "{{ anna_mode_direct != 'heat' }}"
                    sequence:
                      - service: climate.turn_on
                        target: { entity_id: climate.anna }
                      - service: climate.set_hvac_mode
                        target: { entity_id: climate.anna }
                        data: { hvac_mode: heat }
                default: []
              - if:
                  - condition: template
                    value_template: "{{ (target_direct - anna_now_direct) | abs > 0.25 }}"
                then:
                  - service: climate.set_temperature
                    target: { entity_id: climate.anna }
                    data: { temperature: "{{ target_direct }}" }

      # Hoofdlogica
      - variables:
          room_temp: "{{ states('sensor.anna_temperatuur') | float(0) }}"
          temp_req:  "{{ states('sensor.temperature_req') | float(0) }}"
          force_on:  "{{ is_state('input_boolean.heatpump_force','on') }}"
          anna_now:  "{{ state_attr('climate.anna','temperature') | float(0) }}"
          anna_mode: "{{ state_attr('climate.anna','hvac_mode') | default('heat') }}"
          step:      "{{ step_size | float(0.5) }}"

      - variables:
          hp_delta: "{{ (temp_req if temp_req > 0 else 0) | float(0) }}"
          raw_target: "{{ room_temp + hp_delta }}"
          quantized_target: "{{ ((raw_target / step) | round(0) * step) | round(1) }}"
          idle_target: "{{ (((room_temp / step) | floor) * step) | round(1) }}"

      # 1) Geen warmtevraag → pomp uit, Anna ≤ kamertemp
      - choose:
          - conditions: "{{ temp_req <= 0 }}"
            sequence:
              - service: input_number.set_value
                target: { entity_id: input_number.heatpump_setpoint }
                data: { value: 0 }
              - if:
                  - condition: template
                    value_template: "{{ (anna_now - idle_target) | abs > hysteresis }}"
                then:
                  - service: climate.set_temperature
                    target: { entity_id: climate.anna }
                    data: { temperature: "{{ idle_target }}" }

      # 2) Wel warmtevraag → setpoint (delta) bijwerken
      - choose:
          - conditions: "{{ temp_req > 0 }}"
            sequence:
              - service: input_number.set_value
                target: { entity_id: input_number.heatpump_setpoint }
                data: { value: "{{ temp_req }}" }

      # 3) Max kamerdoel bewaken
      - if:
          - condition: template
            value_template: >
              {{ (room_temp + (states('input_number.heatpump_setpoint')|float(0))) > setpoint_max }}
        then:
          - service: input_number.set_value
            target: { entity_id: input_number.heatpump_setpoint }
            data:
              value: "{{ setpoint_max - room_temp }}"

      # 4) Nieuw setpoint naar Anna (alleen bij echte wijziging)
      - variables:
          final_target: "{{ room_temp + (states('input_number.heatpump_setpoint')|float(0)) }}"
          final_target_q: "{{ ((final_target / step) | round(0) * step) | round(1) }}"
      - choose:
          - conditions: "{{ (final_target_q - anna_now) | abs > hysteresis }}"
            sequence:
              - choose:
                  - conditions: "{{ anna_mode != 'heat' }}"
                    sequence:
                      - service: climate.turn_on
                        target: { entity_id: climate.anna }
                      - service: climate.set_hvac_mode
                        target: { entity_id: climate.anna }
                        data: { hvac_mode: heat }
                default: []
              - service: climate.set_temperature
                target: { entity_id: climate.anna }
                data: { temperature: "{{ final_target_q }}" }

Krijg nu ook de meldingen:

The automation "Heatpump Controller" (`automation.heatpump_controller_2`) is not active because the configuration has errors.

Error:`invalid template (TemplateAssertionError: No filter named 'floor'.) for dictionary value @ data['actions'][3]['variables']['idle_target']. Got '{{ (((room_temp / step) | floor) * step) | round(1) }}'`.

To fix this error, [edit the automation](https://xjjshjhbnffhqzezrtz9bjjsdwuhlgiw.ui.nabu.casa/config/automation/edit/heatpump_controller) to correct it, then save and reload the automation configuration.

Kortom: ik heb er een rommel van gemaakt.

Bijgaand een fresh up met de originele logica (die werkt bij mij feilloos), maar met jouw entiteiten. Probeer deze eens. Ik kan het natuurlijk zelf niet testen met jouw entiteiten…

# packages/heatpump_controler_automation.yaml
# PDW logic, aangepast op Bastiaan-entities
# Nieuwe HA syntax (triggers/actions) en zonder bovenliggende pakket-sleutel

input_number:
  heatpump_setpoint:
    name: doeltemperatuur warmtepomp
    icon: mdi:thermometer
    unit_of_measurement: "°C"
    min: -10
    max: 55
    mode: box

  # Gewenste kamertemperatuur (extern instelbaar)
  temperature_target:
    name: Thermostaat doeltemperatuur
    icon: mdi:home-thermometer
    unit_of_measurement: "°C"
    min: 10
    max: 25
    step: 0.5
    mode: box

input_boolean:
  heatpump_force:
    name: Heatpump force
    icon: mdi:heat-pump-outline

template:
  # ---- Niet-trigger-based sensoren ----
  - sensor:
      # Kamertemperatuur uit Anna (1-zone)
      - unique_id: bastiaan_temp_avg
        name: temperature_avg
        icon: mdi:thermometer
        device_class: temperature
        unit_of_measurement: "°C"
        state: >
          {{ states('sensor.anna_temperatuur') | float(0) | round(1) }}

      # Warmtevraag (max(0, target - gemeten))
      - unique_id: bastiaan_temp_req
        name: temperature_req
        icon: mdi:thermometer-plus
        device_class: temperature
        unit_of_measurement: "°C"
        state: >
          {% set raw_req = (
            states('input_number.temperature_target') | float(0)
            - states('sensor.temperature_avg') | float(0)
          ) | round(1) %}
          {{ raw_req if raw_req > 0 else 0 }}

      # In 1-kamer setup is 'generic' gelijk aan 'temperature_req'
      - unique_id: bastiaan_temp_req_generic
        name: temperature_req_generic
        icon: mdi:thermometer-plus
        device_class: temperature
        unit_of_measurement: "°C"
        state: "{{ states('sensor.temperature_req') }}"

      # Delta water ↔ retour (max 30°C)
      - unique_id: bastiaan_delta_water_heat
        name: delta_water_heat
        icon: mdi:thermometer
        unit_of_measurement: "°C"
        state: >
          {% set delta = (
            states('sensor.opentherm_watertemperatuur') | float(0)
            - states('sensor.opentherm_retourtemperatuur') | float(0)
          ) | round(2) %}
          {% if delta > 0 %}
            {{ 30 if delta > 30 else delta }}
          {% else %}
            0
          {% endif %}

      # Verwarmingscapaciteit (gasmodulatie of fallback Shelly)
      - unique_id: bastiaan_heating_capacity
        name: heating_capacity
        unit_of_measurement: "%"
        state: >
          {% if states('sensor.opentherm_modulatieniveau') | float(0) > 0 %}
            {{ states('sensor.opentherm_modulatieniveau') | float(0) }}
          {% else %}
            {% set cap = (
              (states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12)
              / 2500 * 100
            ) | round(1) %}
            {{ 0 if cap < 0 else cap }}
          {% endif %}

      # Warmtepomp-capaciteit uit elektrisch verbruik
      - unique_id: bastiaan_heatpump_capacity
        name: heatpump_capacity
        unit_of_measurement: "%"
        state: >
          {% set cap = (
            (states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12)
            / 25
          ) | round(1) %}
          {{ 0 if cap < 0 else cap }}

    binary_sensor:
      # Binaire status warmtepomp
      - unique_id: bastiaan_heatpump_active
        name: heatpump_active
        icon: mdi:heat-pump-outline
        state: >
          {{
            (
              (states('sensor.shellypro1pm_ec62608c06a8_power') | float(0) - 12)
              / 25
            ) | round(0) > 10
          }}

  # ---- Status-event sensor (trigger-based) ----
  - trigger:
      - trigger: event
        event_type: heatpump_status_value
    sensor:
      - unique_id: bastiaan_heatpump_status
        name: heatpump_status
        icon: mdi:heat-pump-outline
        state: >
          {% set current = this.state | default('', true) %}
          {% if trigger.event.data.value is not defined %}
            {{ current }}
          {% else %}
            {{ trigger.event.data.value }}
          {% endif %}

automation:
  - id: "1663864767086"
    alias: Heatpump Controller
    mode: restart

    variables:
      setpoint_max: 30
      water_temp_max: 52
      water_temp_delta_max: 8

    triggers:
      - trigger: state
        entity_id:
          - sensor.temperature_req_generic
          - sensor.opentherm_modulatieniveau
          - sensor.opentherm_beoogde_keteltemperatuur
          - sensor.heatpump_capacity
        for:
          seconds: 10

    actions:
      # --- Geen warmtevraag ---
      - if:
          - condition: template
            value_template: "{{ states('sensor.temperature_req_generic') | float(0) <= 0 }}"
        then:
          - condition: template
            value_template: "{{ states('input_number.heatpump_setpoint') | float(0) >= 0 }}"
          - action: input_number.set_value
            target:
              entity_id: input_number.heatpump_setpoint
            data:
              value: -1

        # --- Wel warmtevraag ---
        else:
          # Alleen warmtepomp als buiten > 4.5°C én force aan
          - if:
              - condition: state
                entity_id: input_boolean.heatpump_force
                state: "on"
              - condition: template
                value_template: >
                  {{ states('sensor.smile_anna_buitentemperatuur') | float(0) > 4.5 }}
            then:
              # Gas actief? probeer te stoppen
              - if:
                  - condition: template
                    value_template: >
                      {{
                        states('binary_sensor.opentherm_sww_status') == 'off'
                        and states('sensor.opentherm_modulatieniveau') | float(0) > 0
                        and states('sensor.opentherm_retourtemperatuur') | float(0) > 35
                      }}
                then:
                  - action: input_number.set_value
                    target:
                      entity_id: input_number.heatpump_setpoint
                    data:
                      value: -1

                else:
                  # Warmtepompregeling (throttle of 'ease on')
                  - if:
                      - condition: template
                        value_template: >
                          {% set boiler_temp = states('sensor.opentherm_beoogde_keteltemperatuur') | float(0) %}
                          {% set water_temp = states('sensor.opentherm_watertemperatuur') | float(0) %}
                          {% set hp_cap = states('sensor.heatpump_capacity') | float(0) %}
                          {{ (boiler_temp - water_temp > water_temp_delta_max | float(0)) or (hp_cap > 80) }}
                    then:
                      # Throttle naar 0 om WP wel actief te houden
                      - action: input_number.set_value
                        target:
                          entity_id: input_number.heatpump_setpoint
                        data:
                          value: 0
                    else:
                      # Bij grote gap voorzichtig (0.1) om gas-start te voorkomen
                      - if:
                          - condition: template
                            value_template: >
                              {{
                                (
                                  states('sensor.opentherm_beoogde_keteltemperatuur') | float(0)
                                  - states('sensor.opentherm_watertemperatuur') | float(0)
                                ) | abs > 4.5
                              }}
                        then:
                          - action: input_number.set_value
                            target:
                              entity_id: input_number.heatpump_setpoint
                            data:
                              value: 0.1
                        else:
                          # Geen issues: gewoon temperature_req doorgeven
                          - action: input_number.set_value
                            target:
                              entity_id: input_number.heatpump_setpoint
                            data:
                              value: "{{ states('sensor.temperature_req_generic') | float(0) }}"
            else:
              # Hybride/gasmodus: gewoon temperature_req doorgeven
              - action: input_number.set_value
                target:
                  entity_id: input_number.heatpump_setpoint
                data:
                  value: "{{ states('sensor.temperature_req_generic') | float(0) }}"

      # --- Status-update ---
      - event: heatpump_status_value
        event_data:
          value: >
            {% if is_state('binary_sensor.heatpump_active', 'on') %}
            Warmtepomp
            {% elif states('sensor.heating_capacity') | int(0) > 0 %}
            Hybride
            {% else %}
            Inactief
            {% endif %}

      # --- Max setpoint begrenzen ---
      - if:
          - condition: template
            value_template: >
              {{
                (
                  state_attr('climate.anna', 'current_temperature') | float(0)
                  + states('input_number.heatpump_setpoint') | float(0)
                )
                > setpoint_max | float(0)
              }}
        then:
          - action: input_number.set_value
            target:
              entity_id: input_number.heatpump_setpoint
            data:
              value: >
                {{
                  setpoint_max | float(0)
                  - state_attr('climate.anna', 'current_temperature') | float(0)
                }}

      # --- Nieuw setpoint naar Anna toepassen ---
      - if:
          - condition: template
            value_template: >
              {{
                state_attr('climate.anna', 'temperature') | float(0) | round(1)
                != (
                  state_attr('climate.anna', 'current_temperature') | float(0)
                  + states('input_number.heatpump_setpoint') | float(0)
                ) | round(1)
              }}
        then:
          - action: climate.set_temperature
            target:
              entity_id: climate.anna
            data:
              temperature: >
                {{
                  (
                    state_attr('climate.anna', 'current_temperature') | float(0)
                    + states('input_number.heatpump_setpoint') | float(0)
                  ) | round(1)
                }}
          - action: logbook.log
            data:
              name: Verwarming
              message: >
                TEMP SET (
                  {{
                    (
                      state_attr('climate.anna', 'current_temperature') | float(0)
                      + states('input_number.heatpump_setpoint') | float(0)
                    ) | round(1)
                  }}°C ->
                  {{ state_attr('climate.anna', 'temperature') | float(0) }} /
                  {{ state_attr('climate.anna', 'current_temperature') | float(0) }}°C
                )
1 Like

Dank!! Ik heb hem aangepast naar eigen parameters en het draait hier al een zonnetje. Geen gas verbruik (voor cv) meer boven de 4.5 graden!

Dank je PWDonline. Late reactie, kreeg geen notificatie van dit forum. Ik heb je script geplaatst, nu aan het testen. Klopt het dat er geen relatie zit tussen helpers en Anna? Als ik temp instel bij Anna in dashboard gebeurt er niks bij de Helper. En de gevraagde temp daalt nu automatisch waardoor Warmtepomp na minuut uitslaat. (oook geen gasvraag)

Hele gekke vraag misschien… maar zou je op afstand mee mogen willen kijken?

Het idee achter deze opzet is dat het ook multi-zone werkt. Elke zone of ruimte heeft dus een eigen instelling. Dat kan via een slimme radiatorknop/thermostaat, of virtueel via een generic thermostat in Home assistant. Elke zone/ruimte heeft één of meer temperatuur sensoren. (vaak zitten deze in een thermostaat of rookmelder of bewegingsmelder). Via een min/max sensor wordt de gemiddelde temperatuur per ruimte bepaald (zichtbaar boven aan de kaarten het verschil tussen de gemiddelde temperatuur en de ingestelde temperatuue is de temperatuurvraag. De automation gebruikt de temperatuurvraag om de anna te sturen. De anna is dus eigenlijk de thermostaat die de warmtepomp/ketel aanstuurt. kort gezegd wordt de anna dus continue bijgesteld door de automation door de warmte vraag op te tellen bij de door anna gemeten temperatuur. Om te forceren dat de wamtepomp wordt gebruikt, zal hierop binnen bepaalde limieten een correctie op worden doorgevoerd. Belangrijk is ook dat de wamtepomp op een smartplug zit aangesloten, waardoor het verbruik kan worden gemeten. Aan de hand daarvan kan de automation zien hoe hard de warmtepomp moet werken.

Bijgaande screenshots illustreren dit hopelijk een beetje


Overzicht van de ruimtes met generieke thermostaat


Overzicht van een kamer


detail ingezoomd: Verwaming. Verschillende temperatuurmetingen per ruimte


Generieke Instelling/controlpanel van de wamtepomp

Uiteraard kun je me contacten voor meer hulp…

1 Like

Ha PDW, thanks again. Had je mijn bericht/DM op Tweakers gezien?

PS: heb zeker warmtepomp op powerplug zitten :slight_smile: Met de nieuwe set code draait hij niet meer. Mochten we even direct in contact komen zou dat super fijn zijn.