Dynamic list of entities

Is there a simple way to maintain a dinamical list of entities based on wether the value of a related to each entity sensor is over or below a certain threshold?

This is roughly the situation I want the list for:

  1. I have one accumulating electrical heatings in each room of my house (switch in HA).
  2. In each room there’s a temperature sensor (related to each switch).
  3. I want to maintain a dinamical list with the target appliances to switch on.
  4. When the sensor is below a threshold, the corresponding entity is added to the list.
  5. When the sensor is over the threshold, the corresponding entity is removed to the list.
  6. An input_boolean indicates when the electricity tariff is cheap.
  7. When the tariff is cheap and the remaining contracted power is enough to feed a heater, corresponding entity from the list is removed and the switch is set to on. This continues until remaining power is not enough to feed any heater in the list.
  8. Then the tariff is expensive, or remaining power is negative, a switch is set to off and is appended to the list again.
  9. A scheduler is in charge of choosing the next entity to switch on or off.

As you can see, there’s a lot of things to do, but the first thing I’d like to have working is the list object with pop and append features.

I suppose I can do it an integration made in python, but although I program in python, I don’t know how to make a new integration (maybe some day).

I could also make it with a group and several automations and scripts, but I think groups are not intended for this dinamical behaviour.

Can anybody hint me in the correct direction?

You can create a dynamic list of entities with Templating, but AFAIK neither pop() nor append() are available currently.

Thank you!

I’ll look into it, and guess if pop() and append() could be done with automations.

The old-style groups had the according services, but not the new-style ones. Not sure if or when they are going to be removed though.


Some of your list is a bit obscure, but for the most part, you can probably build upon something like this (it’s a bit long, but just one automation and one simple static group, everything else, you should already have in place, more or less…).
You would need:

  • sensor.remaining_contracted_power the sensor you mentioned, update the name as needed.
  • input_boolean.tariff_cheap the input_boolean you mentioned, update the name as needed.
  • switch.all_heaters a group containing all heater switches with “All entities” turned ON (important):
  • A proper naming convention for your heater switches and temperature sensors (if you want/use a different convention, change the code accordingly):
    • Example 1:
      • switch.heater_one
      • sensor.heater_one_temperature
    • Example 2:
      • switch.kitchen_heater
      • sensor.kitchen_heater_temperature

The logic is as follow:

  • Whenever tariff goes cheap, as long as there’s enough power, and at least one heater is off, continuously look for the heater with the lowest associated temperature, and turn it on.
  • Whenever remaining power goes negative, as long as it remains negative, and at least one heater is still on, continuously look for the heater with the highest associated temperature, and turn it off.
  • I didn’t do the “tariff goes expensive” part, since I’m not sure what kind of logic you want to apply here.

Values used for numeric states are totally arbitrary, adapt as needed.
I’m not sure how you intended to do the “pick heater based on scheduler”, so I did the example with lowest/highest temp, but you could change that to a priority+time based logic.

Also, I have no way to actually test all this, so you will probably need to do a bit (lot?) of debugging. Let me know if you find any error, I can edit the code for anyone else looking at it in the future.

description: ""
mode: restart
trigger:
  - platform: state
    entity_id:
      - input_boolean.tariff_cheap
    to: "on"
    id: CHEAP
  - platform: state
    entity_id:
      - input_boolean.tariff_cheap
    to: "off"
    id: EXPENSIVE
  - platform: numeric_state
    entity_id:
      - sensor.remaining_contracted_power
    below: 0
    id: POWER_NEGATIVE
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id:
              - CHEAP
        sequence:
          - repeat:
              sequence:
                - variables:
                    heater_id: >-
                      {%- set ns = namespace(heater='', temperature=999.9) %}
                      {%- for heater_id in state_attr('switch.all_heaters', 'entity_id') %}
                        {%- if is_state(heater_id, 'off') %}
                          {%- set temp = states(heater_id | replace('switch', 'sensor') + '_temperature')) | float(999.9) %}
                          {%- if temp < ns.temperature %}
                            {%- set ns.heater = heater_id %}
                            {%- set ns.temperature = temp %}
                          {%- endif %}
                        {%- endif %}
                      {%- endfor %}
                      {{ ns.heater }}
                - service: switch.turn_on
                  target:
                    entity_id: "{{ heater_id }}"
                  data: {}
              while:
                - condition: and
                  conditions:
                    - condition: numeric_state
                      entity_id: sensor.remaining_contracted_power
                      above: 500
                    - condition: state
                      entity_id: switch.all_heaters
                      state: "off"
      - conditions:
          - condition: trigger
            id:
              - POWER_NEGATIVE
        sequence:
          - repeat:
              sequence:
                - variables:
                    heater_id: >-
                      {%- set ns = namespace(heater='', temperature=-999.9) %}
                      {%- for heater_id in state_attr('switch.all_heaters', 'entity_id') %}
                        {%- if is_state(heater_id, 'on') %}
                          {%- set temp = states(heater_id | replace('switch', 'sensor') + '_temperature')) | float(-999.9) %}
                          {%- if temp > ns.temperature %}
                            {%- set ns.heater = heater_id %}
                            {%- set ns.temperature = temp %}
                          {%- endif %}
                        {%- endif %}
                      {%- endfor %}
                      {{ ns.heater }}
                - service: switch.turn_off
                  target:
                    entity_id: "{{ heater_id }}"
                  data: {}
              while:
                - condition: and
                  conditions:
                    - condition: numeric_state
                      entity_id: sensor.remaining_contracted_power
                      below: 0
                    - condition: template
                      value_template: >-
                        {%- for heater_id in state_attr('switch.all_heaters', 'entity_id') %}
                          {%- if is_state(heater_id, 'on') %}
                            {{ true }}
                          {%- endif %}
                        {%- endfor %}

                        {{ false }}
      - conditions:
          - condition: trigger
            id:
              - EXPENSIVE
        sequence: []
1 Like

Wow!

Thank you, so much!!!

I’ll try and adapt it :slight_smile:

1 Like