Rejectattr comparison of two attributes

Example code (from using the templates editor to debug what I’m working toward):

{% for rad in states.climate|rejectattr('attributes.hidden')|rejectattr('attributes.temperature', 'ge', 20.6) -%}
{{ rad.name }} currently {{ rad.attributes.temperature }} {{ rad.attributes.temperature - rad.attributes.current_temperature }}
{% endfor %}

what I would like to be able to do:

{% for rad in states.climate|rejectattr('attributes.hidden')|rejectattr('attributes.temperature', 'ge', 'attributes.current_temperature') -%}
{{ rad.name }} currently {{ rad.attributes.temperature }} {{ rad.attributes.temperature - rad.attributes.current_temperature }}
{% endfor %}

To exclude all the radiators where the current temperature is greater or equal to the desired temperature (actually, even more ideally, I’d like to be able to apply a small delta… something like

{% for rad in states.climate|rejectattr('attributes.hidden')|rejecteval('attributes.current_temperature > attributes.temperature - 0.3') -%}

Which kind of looked like “map” rather than “rejecteval” (which I made up) might work, but I got stuck looking for an example where I could use an expression rather than a built in filter such as “lower”.

I’ve played around, searched the forums and Jinja2 documentation, but not been able to find anything relevant, so any pointers would be great.

Just as a bit of background, the radiators have a Eurotronic Spiritz TRV (which suffers from bug Z-Wave State for ‘SwitchMultiLevel’ is Ignored so you can’t actually tell if the valve is open, so this was my attempted workaround to control the boiler so it runs only if the TRV is calling for heat).

That makes no sense. Your current temperature will always be equal to your current_temperature.

So I’m going to assume that’s a typo and you want to compare this against a different attribute inside your object.

{% for rad in states.climate|rejectattr('attributes.hidden') %}
  {% if rad.attributes.current_temperature > rad.attributes.desired_temperature - 0.3 %}
    {{ rad.name }} currently {{ rad.attributes.temperature }} {{ rad.attributes.temperature - rad.attributes.current_temperature }}
  {% endif %}
{% endfor %}

Sorry - yes (edited/corrected now), I want to compare temperature (the desired temperature) against current_temperature.

With your suggestion is it possible to then go on to count or add the result? I was working toward something like:

{% if states.climate|rejectattr('attributes.hidden')|rejectattr('attributes.temperature', 'ge', 'attributes.current_temperature')|map(attribute='temperature')|map('float')|sum - states.climate|rejectattr('attributes.hidden')|rejectattr('attributes.temperature', 'ge', 'attributes.current_temperature')|map(attribute='current_temperature')|map('float')|sum > 0.3 -%}
    boiler.turn_on
  {% else %}
    bopiler.turn_off
  {% endif %}

Looking at the Jinja2 documentation for variables, it doesn’t appear that I can create a local one to sum up the temperature?

{% total_temp = 0.0 %}
{% for rad in states.climate|rejectattr('attributes.hidden') %}
  {% if rad.attributes.current_temperature > rad.attributes.desired_temperature %}
    {{ rad.name }} currently {{ rad.attributes.temperature }} {{ rad.attributes.temperature - rad.attributes.current_temperature }}
    {% total_temp = total_temp + rad.attributes.temperature - rad.attributes.current_temperature
  {% endif %}
{% endfor %}
{% if total_temp > 0.3 %}
    boiler.turn_on
{% else %}
    bopiler.turn_off
{% endif %}

Ooh… found that for’s can have conditions… that may be helpful

{% for rad in states.climate|rejectattr('attributes.hidden') if rad.attributes.temperature > rad.attributes.current_temperature + 0.3 -%}
{{ rad.name }} currently {{ rad.attributes.current_temperature }} vs desired {{ rad.attributes.temperature }}
{% if loop.last %}
    boiler.turn_on
{% endif %}
{% else %}
    boiler.turn_off
{% endfor %}

I’ll have a play with this - the {% else %} here is the magic “else” for a for block which only executes if the for block would iterate over no items.

You cannot do this. Jinja is limited in scope. You could do this with typical filtering but you are trying to access 2 pieces of information and compare them. Because of this, you have to essentially jump through hoops. If you create a macro and then parse it into a list we can do it.

{%- macro get_entities() %}
{%- for rad in states.climate|rejectattr('attributes.hidden') %}
  {%- if rad.attributes.current_temperature > rad.attributes.desired_temperature %}
    {{- rad.entity_id }}
  {%- endif %}
  {%- if not loop.last -%}
    ,
  {%- endif %}
{%- endfor %}
{%- endmacro %}
{% set entities = get_entities().split(',') %}
{% set state_objects = states | selectattr('entity_id', 'in', entities ) %}
{{ state_objects | length }}
{{ state_objects | sum(attribute='attributes.current_temperature') }}
1 Like

Thanks. For now, it looks like the for/if combination is giving me the results I want, but the macro example is also a useful example.