Use of variables in template statements

I am experimenting with the newly introduced variables and am having problems understanding where they can be used. E.g., in a script sequence:

- variables:
  home: '{{ (states("group.familie") == "home") }}'
  time: '{{ now().strftime("%H:%M:%S") }}'
  daytime: '{{ (time > states("input_datetime.off")) and (time < states("input_datetime.on")) }}'
  armed: '{{ states("alarm_control_panel.home") == "armed_away" }}'

expressions works perfectly fine (e.g. time is used and resolved in daytime). However it seems that using them in statements:

  service_to_call: >-      
    {% if (home and daytime and armed) %}
      alarm_control_panel.alarm_disarm
    {% elif (((not home) or (not daytime)) and (not armed)) %}
      alarm_control_panel.alarm_arm_away
    {% else %}
      script.noop
    {% endif %}

doesn’t seem to resolve them properly or at all. In this case the ‘if’ branch is always true.

I’m dumping the content of the variables into the log file within the actions and the variables all have the expected values.

Do I miss anything or I am I completely misunderstanding how to use variables?

yes it’s always true because all variables are strings. if you perform an if statement checking for contents of a string, it will always resolve true. You need to convert the values to the types that they should be. Unfortunately, there is no bool filter, so you have to use from_json…

  service_to_call: >-      
    {% if (home | from_json and daytime | from_json and armed | from_json) %}
      alarm_control_panel.alarm_disarm
    {% elif (((not home | from_json) or (not daytime | from_json)) and (not armed | from_json)) %}
      alarm_control_panel.alarm_arm_away
    {% else %}
      script.noop
    {% endif %}

EDIT: I should mention that this is probably changing in 0.117 and variables should actually be the type you output in your templates.

Thanks @petro for the quick response. Unfortunately this also doesn’t seem to work, it’s giving a runtime error on the json conversion. Nonetheless your response allowed me to define it in a way that is working. Here’s how it looks like:

check_the_truth:
  sequence:
  - variables:
      a_true_thing: '{{ 6==9 }}'
      really_a_true_thing: '{{ a_true_thing }}'
      the_output: >-
        {% if (really_a_true_thing) %}
          you did not cheat
        {% else %}
          you cheated
        {% endif %}
  - service: system_log.write
    data:
      message: 'a_true_thing:{{ a_true_thing }}, really_a_true_thing:{{ really_a_true_thing }}, the_output:{{ the_output }}'
      level: warning

one would expect this to output that I cheated but it doesn’t - because of the ‘if’ clause always being true as really_a_true_thing is a string and not a bool - as you said.

2020-10-24 06:51:17 WARNING (MainThread) [homeassistant.components.system_log.external] a_true_thing:False, really_a_true_thing:False, the_output:you did not cheat

using your suggestion above

 {% if (really_a_true_thing | from_json) %}

leads to this runtime error (with a long stackdump in the log)

2020-10-24 06:58:32 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection.2748428216] JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The solution/workaround is to do a string comparison in the if statement

{% if (really_a_true_thing == "True") %}

which then gives the expected result

2020-10-24 07:02:11 WARNING (MainThread) [homeassistant.components.system_log.external] a_true_thing:False, really_a_true_thing:False, the_output:you cheated

Not pretty but workable. I am looking forward to the improvement you mentioned, variables carrying their native type. That would make this simpler and better looking :wink:

Btw, I was wrong saying it works in expressions - it doesn’t. It just happened that the string comparison in that section worked.

Again, thanks for your quick response and sending me down the right path !