Dynamic priority allocation

Hello there!

For my other project (Photovoltaics (PV) + battery + hass = maximize auto-consumption) I was looking for a way to turn on/off devices, depending on the priority that I allocate to them. The device with the highest priority will be switched on first, followed by the prio2 device, etc. The same goes for switching off devices in case of insufficient power: First, I want to switch off pri3 devices, followed by prio2 and eventually prio1.

You could imagine that there’s no easy way to dynamically switch on and off devices, based on their priority as one of the main energy consumers and their authorization (unlocked and not running). Therefore I wrote this small configuration so that you can use it as well.

You could adapt this example for other devices that can be switched on or off and where you want to be able to define priorities upfront.

Here’s how I did it:

The input_select section first of all defines all (3) consumers are part of the devices that I want to allocate priorities to.

input_select:

  prio1_consumer:
    name: Priority 1 consumer
    options:
      - ev charge
      - hot water
      - heat pump
    initial: heat pump
    icon: mdi:arrow-up-circle

  prio2_consumer:
    name: Priority 2 consumer
    options:
      - ev charge
      - hot water
      - heat pump
    initial: ev charge
    icon: mdi:arrow-right-circle

  prio3_consumer:
    name: Priority 3 consumer
    options:
      - ev charge
      - hot water
      - heat pump
    initial: hot water
    icon: mdi:arrow-down-circle

[Note: I wonder if there’s a more intelligent way to define the priorities for the consumers, maybe a drop-down list that only shows values that are available (especially in prio 2 where the prio 1 value has already been defined upfront)]

In a second step, the binary_sensor section provides an answer to the question “has the usage of the device been authorized?”. In my use case, this depends on various variables that must be met as well as the state of the device which must be switched off. The device will only be considered in a dynamic automation if the authorization binary sensor shows “true”.

binary_sensor:

       ### authorization template sensor for energy consumers
       ### means "I am ready to be switched on and do what I'm supposed to do" = there's a need and the device's state is switched off
       
  - platform: template
    sensors:
      auth_heat_pump:  # Heat Pump = aus, Heizmodus = an, aureichend Licht, nicht Sommerzeit, kalte Temperaturen 
        value_template: "{{ is_state('switch.heat_pump','off') and (states('sensor.luxtronik_id_web_temperatur_trl') < states('sensor.luxtronik_id_web_temperatur_trl_hz')) and states.sensor.remaining_pv_light.state | float >= 1.5 and states.sensor.season.state != 'summer' and (states.sensor.luxtronik_id_web_mitteltemperatur.state | int < 10 or states.sensor.dark_sky_overnight_low_temperature_0.state | int < 15) }}"      
        friendly_name: "heat pump authorized"
      auth_hot_water: 
        value_template: "{{ is_state('switch.hot_water_template_switch', 'off') and is_state('binary_sensor.water_hot', 'off') }}"
        friendly_name: "hot water boiler authorized"
      auth_ev_charge: # muss später geändert werden auf "plugged in", ohne minimum cumulated production value
        value_template: "{{ is_state('switch.ev_charge', 'off') and states.sensor.cumulated_production_5min_mean.state | int > 2500 }}"
        friendly_name: "EV Charge authorized"
  sensor:

      dynamic_priority_consumer:
        friendly_name: "next consumer to switch on"
        value_template: >
          {% if is_state('input_select.prio1_consumer', 'heat pump')  %}
            {% if is_state('binary_sensor.auth_heat_pump', 'on') %}
                      heat pump
            {% elif is_state('input_select.prio2_consumer', 'hot water') and is_state('binary_sensor.auth_hot_water', 'on') %}
                        hot water
            {% elif is_state('input_select.prio2_consumer', 'ev charge') and is_state('binary_sensor.auth_ev_charge', 'on') %} 
                       ev charge    
            {% else %}
                      {{ states.input_select.prio3_consumer.state }}  
            {% endif %}

          {% elif is_state('input_select.prio1_consumer', 'hot water')  %}
            {% if is_state('binary_sensor.auth_hot_water', 'on') %}
                          hot water
            {% elif is_state('input_select.prio2_consumer', 'ev charge') and is_state('binary_sensor.auth_ev_charge', 'on') %} 
                           ev charge    
            {% elif is_state('input_select.prio2_consumer', 'heat pump') and is_state('binary_sensor.auth_heat_pump', 'on') %} 
                           heat pump
            {% else %}
                          {{ states.input_select.prio3_consumer.state }}  
            {% endif %}

          {% elif is_state('input_select.prio1_consumer', 'ev charge')  %}
            {% if is_state('binary_sensor.auth_ev_charge', 'on') %}
                          ev charge
            {% elif is_state('input_select.prio2_consumer', 'hot water') and is_state('binary_sensor.auth_hot_water', 'on') %}
                            hot water
            {% elif is_state('input_select.prio2_consumer', 'heat pump') and is_state('binary_sensor.auth_heat_pump', 'on') %} 
                           heat pump
            {% else %}
                          {{ states.input_select.prio3_consumer.state }}  
            {% endif %}
          {% endif %}
          
      dynamic_shutdown_consumer:
        friendly_name: "consumer to switch off next"
        value_template: >          
          {% if is_state('input_select.prio3_consumer', 'heat pump')  %}
            {% if is_state('switch.heat_pump', 'on') %}
                          heat pump
            {% elif is_state('input_select.prio2_consumer', 'hot water')  and is_state('switch.hot_water_template_switch', 'on') %}
                          hot water
            {% elif is_state('input_select.prio2_consumer', 'ev charge')  and is_state('switch.ev_charge', 'on') %}
                          ev charge
            {% else %}
                          {{ states.input_select.prio1_consumer.state }}
            {% endif %}

          {% elif is_state('input_select.prio3_consumer', 'hot water') %}
            {% if is_state('switch.hot_water_template_switch', 'on') %}
                            hot water
            {% elif is_state('input_select.prio2_consumer', 'heat pump')  and is_state('switch.heat_pump', 'on') %}
                          heat pump
            
            {% elif is_state('input_select.prio2_consumer', 'ev charge')  and is_state('switch.ev_charge', 'on') %}
                          ev charge
            {% else %}
                          {{ states.input_select.prio1_consumer.state }}
            {% endif %}

          {% elif is_state('input_select.prio3_consumer', 'ev charge') %}
            {% if is_state('switch.ev_charge', 'on') %}
                         ev charge
            {% elif is_state('input_select.prio2_consumer', 'heat pump')  and is_state('switch.heat_pump', 'on') %}
                          heat pump
            
            {% elif is_state('input_select.prio2_consumer', 'hot water') and is_state('switch.hot_water_template_switch' , 'on') %}
                          hot water
            {% else %}
                          {{ states.input_select.prio1_consumer.state }}
                {% endif %}
          {% endif %}    

Having done the heavy calculation in the sensor and binary_sensor sections, the automation itself is pretty basic. As HASS always calculates the next device to be switched on/off in real time, the automation merely needs to call these devices, without knowing any more details.

automation:

  trigger: "your start trigger"  
  action:
    - service: switch.turn_on
      data_template:
        entity_id: >
          {% if is_state('sensor.dynamic_priority_consumer', 'heat pump') %} switch.heat_pump
          {% elif is_state('sensor.dynamic_priority_consumer', 'hot water') %} switch.hot_water_template_switch
          {% elif is_state('sensor.dynamic_priority_consumer', 'ev charge') %} switch.ev_charging_authorization
          {% endif %}

  trigger: "your stop trigger"
  action:
    - service: switch.turn_off
      data_template:
        entity_id: >
          {% if is_state('sensor.dynamic_shutdown_consumer', 'hot water') %}   switch.hot_water_template_switch
          {% elif is_state('sensor.dynamic_shutdown_consumer', 'ev charge') %} switch.ev_charging_authorization          
          {%endif%}
8 Likes

Thanks - I am looking to do something similar for my apartment and you have given a great guide on how to start (more like shamelessly copy) :grin:
I appreciate that you shared your work with the community. Thanks once again

1 Like