Median Value over States

I’ve scoured google and forums to no avail on this one, but is there an elegant way to return the state of “most items”? For example, I can use a min_max sensor template to give me the median value of temperature sensors in my setup. But I can not use the same sensor template to give the median value of most of the lights in my setup. For example, I want a sensor that tells me if ‘most’ of my lights are on. Ie if 3 of 5 lights are on, the template is ‘on’, if 1 of 5 lights are on, the template is ‘off’. I can hack together something like this which works (just fine) but it is a menace to maintain. It is not elegant, and in my mind, the min_max sensor should (but does not) iterate over non-numeric states.

  - platform: template
    sensors:
        lights:
            friendly_name: "State of Most Lights"
            value_template: >
                {{ (
                (not is_state('light.desk_lamp','off')) | int + 
                (not is_state('light.lounge','off')) | int + 
                (not is_state('light.tv_light_strip','off')) | int + 
                (not is_state('light.mood_light','off')) | int + 
                (not is_state('light.bedside','off')) | int
                ) >= 3 }}

Thanks for any insight here.

How do you want to define the list of lights to consider? Do you want every light in your system, or do you want to manually type in the list of entities, etc.?

Here’s a template you can play with in the template editor:

{% set light_entities = [
    'light.desk_lamp',
    'light.lounge',
    'light.tv_light_strip',
    'light.mood_light',
    'light.bedside'
    ] %}
{{ light_entities | select('is_state','on') | list | count / light_entities | count >= 0.5  }}

This is the best solution that I’ve come up with; I’m happy for now selecting all lights within the Light domain, however it would be ideal if the min_max sensor would simply iterate over a list of entities or specified domain based on an attribute.

sensor:
  - platform: template
    sensors:
        lights:
            friendly_name: "State of Most Lights"
            value_template: > 
                {{ not ((states.light | selectattr('state', 'eq', 'off') | list | count) / (states.light | list | count)) | round(0) | bool }} #Assume off if specified off, otherwise if undefined or on, assume on

# Replace value_template above to assume on if specified on, otherwise if undefined or off, assume off
# {{ ((states.light | selectattr('state', 'eq', 'on') | list | count) / (states.light | list | count)) | round(0) | bool }} 

Just be aware that any non-zero number converted to boolean will be true so your template just tells you if any light is on (since you negate it with not).

You could just replace the definition of light_entities in my code with

{% set light_entities = states.light | map(attribute='entity_id') | list %}

That way you don’t have to iterate through the light domain twice.

Have modified it - I’m in two minds here as to which is best; if it returns an undefined, I think I’d prefer it to assume it’s on rather than off (hence my original negated output). If the light state is explicitly off, then it counts as off; whereas if it’s on or unknown, it assumes it’s on.

As modified above, the code assume’s that if explicitly on, it counts as on, whereas ‘off’ or ‘unknown’ assumes it’s off.