Passes true for condition in developer tools, but fails condition when it runs

Hi all,

I have this automation that tells me if a identified person lost weight compared to the previous day. Or it should anyway!

I have a sensor.person_weight (that is triggered by an xiaomi scale/integration) that holds just the weight recording (and a timestamp + bmi) and a sensor.person_weight_history (sensor constructed separately) that holds a history of up to 5 previous weight recordings (as well as some other items).

state_attr(‘sensor.person_weight_history’,‘history’):

  [{'weight': 107.2, 'bmi': 32.72, 'time': '2023-05-09 06:53:20'}, {'weight': 107.2, 'bmi': 32.72, 'time': '2023-05-09 06:53:13'}, {'weight': 107.2, 'bmi': 32.72, 'time': '2023-05-09 06:53:11'}, {'weight': 108.2, 'bmi': 33.03, 'time': '2023-05-08 18:38:57'}, {'weight': 108.2, 'bmi': 33.03, 'time': '2023-05-08 18:38:54'}]

{{ states(‘sensor.atv_weight’) }}:

107.2

In my automation (that triggers upon when sensor.atv_weight changes) i have a template condition as follows:

 {{ states('sensor.atv_weight') != 'unknown' or 'unavailable' }}
  {% set w=state_attr('sensor.atv_weight_history','history') %} 
  {{ w if w is iterable and w|count > 0 and w[0].weight is defined }}

  {{ state_attr('sensor.atv_weight','weight') < w[1].weight or
  state_attr('sensor.atv_weight','weight') < w[2].weight or
  state_attr('sensor.atv_weight','weight') < w[3].weight and 
  state_attr('sensor.atv_weight','timestamp')[8:10] > w[1].time[8:10] or
  state_attr('sensor.atv_weight','timestamp')[8:10] > w[2].time[8:10] or 
  state_attr('sensor.atv_weight','timestamp')[8:10] > w[3].time[8:10]}}

As the xiaomi scale records up to 3 recordings, i chose to compare to check at least one extra item and start at [1] rather then [0]. The above of course checks if weight was lost and if the data is larger then yesterday.

Now when i go in developer tools, it passes as true. But when the automation runs and i look in the trace, the condition always fails and i’m not sure why. Wish there was some sort of step method to go through a live automation.

Thanks for reading.

Just add some print out lines to check progress.

1 Like

That is not a template condition. Template conditions are required to return true or false. You have three separate print statements that will return all of this:

true or false
a list or an error, see below
true or false

Where is the else case for this?

{{ w if w is iterable and w|count > 0 and w[0].weight is defined }}

You probably want something like this assuming all have to be true:

condition:
  - condition: template
    value_template: "{{ states('sensor.atv_weight') not in ['unknown', 'unavailable'] }}"
  - condition: template
    value_template: >
      {% set history = state_attr('sensor.atv_weight_history','history') %} 
      {{ history is iterable and history|count > 0 and history[0].weight is defined }}
  - condition: template
    value_template: >
      {% set history = state_attr('sensor.atv_weight_history','history') %} 
      {% set weight = state_attr('sensor.atv_weight','weight') %} 
      {% set time = state_attr('sensor.atv_weight','timestamp') %} 
      {{ ( weight < history[1].weight and time[8:10] > history[1].time[8:10] ) or
         ( weight < history[2].weight and time[8:10] > history[2].time[8:10] ) or
         ( weight < history[3].weight and time[8:10] > history[3].time[8:10] ) }}

That is not a template condition. Template conditions are required to return true or false . You have three separate print statements that will return all of this:

Ah got it. I guess it’s more of a multi template condition then? I guess i got confused with the development tools as it states (true) but obviously it states it for every condition i put in, not for the sum of all.

{{ w if w is iterable and w|count > 0 and w[0].weight is defined }}

I didn’t add an else case, probably should have. :thinking:

I just edited my suggested condition above. Not sure if the weight and time logic is correct. The way you had it the time conditions were only ANDed with the third weight. I have them each ANDed with their respective weight conditions.

Basically the logic is:
If i encounter an eligible entry in [1 2 or 3], that is one or more days is past, and the weight has dropped then it should be true.

I think mine was wrong, i intended the time condition to be ANDed against all weight conditions as well.

So this basically splits it up in multiple conditions. I will try this, i’m sure your suggestion will work. It’s a shame development tools doesn’t really tell you this (end result is still true and output is string) but i guess it can’t cover everything.

Many thanks!

1 Like

PS thank you, if i didn’t already. It works great!

Hi all
I would like to share my code example I think is relevant here. It compares recent weight with previous and with average. I’m using it for tts announcements. Talking scales :slight_smile:

And code:

Darius  weight is {{ states('sensor.darius_weight_2')| round(0)}} kg. Which is  
{% set history = state_attr('sensor.darius_weight_history','history') %} 
{% set weight = state_attr('sensor.darius_weight_2','weight') %}
{% set history_average = history|sum(attribute='weight')/21 %}
{{ ((weight-(history[3].weight))*1000)| round (0)|abs }} grams   
{% if (weight>history[3].weight) %} more 
{% else %} less
{% endif %} than last measurement. Or
{{ ((weight-(history_average))*1000)| round (0)|abs }} grams 
{% if (weight>history_average) %} more
{% else %} less
{% endif %} than average. 
1 Like

Nice! The problem with the xiaomi scale it that it reports 3 different values when you do a weigh in and i guess it takes the average of that, it’s a bit vague. But as you don’t always know up front which one is the correct one it’s hard to discard the rest of them. I guess i’ll have to take the average as well.