How to test a list of entities supplied in a blueprint input?

I have a little programming challenge – presumably possible in a template with a for-loop?

I have a blueprint !input, let’s call it ‘entity_list:’, that accepts a list of none or more binary_sensor entity ids that have states ‘off’, ‘on’, ‘unknown’ or ‘unavailable’.

I want to write a template that returns ‘true’ if ANY ONE of the list matches a given condition (‘off’ or ‘on’), ‘false’ otherwise, including the case where the list is empty.

It will itself be used as a state condition (if any of these are ‘on’, do that… )

(Of course, if I give the list straight to the state condition it returns ‘true’ only if ALL the entities match the condition).

Can someone give a newbie a leg-up?

You can use the selectattr filter to select by state, then compare the number of remaining objects in the list to 0.

{{ expand(entity_list) | selectattr('state', 'eq', 'on') 
| list | count  > 0 }}

Many thanks. Looks elegant but it did not work “out of the box” in the template Editor. It works with a list of none or one items but is always false for more than that. I suspect I am not formatting my list correctly (as it would come from blueprint input)?

{% set entities_list = "- binary_sensor.test_door_or_window_open_sensor_1\n- binary_sensor.test_door_or_window_open_sensor_2" %}
{{ entities_list }}

{{ expand(entities_list) | selectattr('state', 'eq', 'on') 
| list | count  > 0 }}

I tried various combinations of quotes, dashes commas and newlines around the entities in entities_list, but all gave the same result. I did not find any documentation at this level of detail … ?

To test them in the Template editor, lists should be wrapped in [ ] and comma-separated.

{% set entities_list = ["binary_sensor.test_door_or_window_open_sensor_1",  "binary_sensor.test_door_or_window_open_sensor_2"] %}
{{ entities_list }}

Thanks! That moves me forward. The ‘on’ case now works in the template editor. I hope that ‘expand’ will still work the same with a list from a blueprint input?

Unfortunately it does not work for the ‘off’ case. It seems that the ‘state’ attribute is bundling ‘unknown’ and ‘unavailable’ with ‘off’, so I only get ‘false’ if both are ‘on’. I want true if either or both are ‘off’, but not ‘unknown’ or ‘unavailable’. Is there any other attribute or test that I can do? I have too little information about the dictionary structure for binary sensors in Home Assistant…

I haven’t done much with Blueprints, so that’s beyond my knowledge.

I misunderstood that point from your original post. I thought you were talking about 2 separate conditions, not combining ‘on’ and ‘off’…

You can select by testing against a list of states using the in test:

| selectattr('state', 'in', ['on', 'off'])

State Object

I think the problem is that the ‘state’ attribute is not set to ‘unknown’ or ‘unavailable’. Selectattr matches both of them to ‘off’. So …

{{ expand(entities_list2) | selectattr('state', 'eq', 'unknown') | list | count  > 0 }}

… yields ‘false’ even if I set both sensors to ‘unknown’.

Or to put it another way …

{{ expand(entities_list2) | selectattr('state', 'in', ['on', 'unknown', 'unavailable' ]) | list | count  > 0 }}

… yields ‘true’ if either sensor is ‘on’ but false otherwise.

The situation is that I want to test whether a room is unoccupied. If it is unoccupied for a while, the heating goes off. Occupancy sensors are ‘on’ (shown as ‘detected’) if there is someone in the room. If there are two or more sensors, then I take any one of them being ‘on’ to mean the room is occupied. If they are unknown or unavailable, I want to ignore them (or treat them as ‘on’). So all sensors ‘off’ (and not ‘unknown’ or ‘unavailable’) is the only condition that means the room is unoccupied. How do I get that out of the entities list?

While I don’t see evidence of the type of “bundling” of unknown and unavailable with off as you’ve described, I think it would be best to just reject them instead of trying to integrate them with ‘on’… If the heater in question is thermostatically controlled, I’d rather it default to stay “on” according to the thermostat rather than the frustration of it staying off even though I’m in the room just because one presence/motion sensor is unavailable.

If we reject the “un’s”, when no binary sensors are “on”… they must all be “off”.

{{ expand(entities_list) 
| rejectattr('state', 'in', ['unknown', 'unavailable'])
| selectattr('state', 'eq', 'on') 
| list | count == 0 }}

Just wanted to add a small detail, you don’t really need expand for this anymore now that is_state has become a jinja test and supports a list of values to compare against. So you can just do this:

{{ entities_list2 | select('is_state', ['on', 'unknown', 'unavailable' ]) | list | count  > 0 }}
1 Like

Correct logic but same problem: ‘unknown’ and ‘unavailable’ are not coming through as matches in any of my example; they match with ‘off’, so the logic fails.

Perhaps this is just my test set-up? I am using input_select (aka dropdown) helpers to select one of the four values of the two door_or_window sensors and the two occupancy sensors. I then use a template sensor to translate that to a sensor of the correct type. It looks fine on a dashboard, but would the behaviour of this be different from a ‘real’ sensor? The trouble is that ‘unknown’ or ‘unavailable’ are difficult to bring about with a real ZigBee sensor!

Here are my test sensors:

### Test door or window open sensor 1
- binary_sensor: 
  - name: Test door or window open sensor 1
    unique_id: "f6bb032a-eb7a-4809-b9af-505f95600c2f"
    icon: mdi:window-closed-variant
    state: "{{ states('input_select.test_door_or_window_selector_1') }}"
    device_class: opening

### Test door or window open sensor 2
- binary_sensor: 
  - name: Test door or window open sensor 2
    unique_id: "48d2c2a1-58cc-4e1c-9d76-30609d1f0e31"
    icon: mdi:window-closed-variant
    state: "{{ states('input_select.test_door_or_window_selector_2') }}"
    device_class: opening

### Test occupancy sensor 1
- binary_sensor: 
  - name: Test occupancy sensor 1
    unique_id: "cecbb15c-3623-43e7-908a-f15bc2a6118f"
    icon: mdi:motion-sensor
    state: "{{ states('input_select.test_occupancy_selector_1') }}"
    device_class: occupancy 

### Test occupancy sensor 2
- binary_sensor: 
  - name: Test occupancy sensor 2
    unique_id: "ec0eb54e-0301-4a67-89f1-a814f2917840"
    icon: mdi:motion-sensor
    state: "{{ states('input_select.test_occupancy_selector_2') }}"
    device_class: occupancy

Thanks for that simplification. The code …

{% set entities_list2 = ["binary_sensor.test_occupancy_sensor_1",  "binary_sensor.test_occupancy_sensor_2"] %}
{{ entities_list2 | select('is_state', ['on', 'unknown', 'unavailable' ]) | list | count > 0 }}

… runs OK in the template editor but with the same problem as all the other variants – ‘unknown’ and ‘unavailable’ do not match those strings in the test but do match ‘off’. Mmmm.

Remove the batteries… :slight_smile:

Seriously though, for your test setup add an availability for each of your binary sensors. Otherwise, any value of the input select other than “on” or “off” will cause the binary sensor to default to “off”.

### Test occupancy sensor 1
- binary_sensor: 
  - name: Test occupancy sensor 1
    unique_id: "cecbb15c-3623-43e7-908a-f15bc2a6118f"
    icon: mdi:motion-sensor
    state: "{{ states('input_select.test_occupancy_selector_1') }}"
    device_class: occupancy 
    availability: >
      {{ is_state('input_select.test_occupancy_selector_1', ['on', 'off']) }}

Can do that but then you have to wait 21600 seconds before ZHA notices and there is not an easy way to change that :thinking:

Why? Is ‘availability’ a separate attribute? If so, is it something that can be tested separately?

Basically, your test setup is flawed… the lack of a defined availability is what’s causing the “bundling” issue.

It would probably be better to use the affirmative instead of the negative version I posted earlier…

    availability: >
      {{ is_state('input_select.test_occupancy_selector_1', ['on', 'off']) }}

I tried that (without really understanding what I am doing) and it did not work. Same results as before.
I do not know why exactly, but I concluded that the test setup is part of the problem because I get different results with real device entities that are unavailable.

Mysteriously not working. The template evaluates correctly, but the sensor always shows ‘unavailable’. If I substitute “true”, however, the sensor is available but shows ‘clear’ on the dashboard if I set it to ‘unknown’ or ‘unavailable’. Meanwhile, the test sensor without this additional line IS showing unavailable on the dashboard but not matching it in the template test. :roll_eyes: :thinking: :woozy_face:


Putting together all of the above – thanks to both @Didgeridrew and @CentralCommand – I think the clearest correct solution is as follows:

For doors or windows opened

The entities list is a list of binary sensors of the device class 'opening', which yield 'on' for 'open' and 'off' for closed. The requirement is that if any one device shows 'on' (open) then the condition is true and the heating is turned off. If all sensors are off, or unavailable, or there are no sensors (empty list) then the automation acts as if all doors and windows are closed.
{{ entities_list | select ('is_state', 'on') | list | count > 0 }}

For room unoccupancy

The entities list is a list of binary sensors of device class 'occupancy', which yield 'on' for 'detected' (occupied) or 'off' for 'clear' (unoccupied). The requirement is that the room is regarded as occupied if any one working sensor is on, or there are none (empty list). Sensors that are 'unknown' or 'unavailable' are ignored, so that the room is regarded as occupied by default. I want true for unoccupied, so the NOT occupied determines that the heating will be turned off.
{{ not entities_list | reject ('is_state', [ 'unknown',  'unavailable' ] ) select ('is_state', 'on') | list | count > 0 }}

I had trouble testing the unknown and unavailable conditions with a dummy test sensor operated by a dropdown input_select list, but I will solve that problem another day.

I tested the template with lists containing various combinations of real unavailable entities and dummy test entities it worked correctly in the HA template editor.

{% set entities_list = ["", "binary_sensor.yyy", "binary_sensor.xzzz"] %}

The next step is to try it in the Blueprint. I hope the entity lists there wok in the same way as my test lists!

Thanks! :+1: :clap: