Use of {{trigger.to_state.state}}

Okay, so of late I’ve noticed spurious errors in my logs related to the above.
The idea behind this is that you provide all the logic in one Binary_Sensor eg: -

      bs_pifi01_timeslot_on:
        value_template: >
          {% set time = states('sensor.time') %}
          {% set slt1en = is_state('input_boolean.ib_switch_pifi01_timeslot1_enable', 'on') %}
          {% set slt1start = states('input_datetime.id_switch_pifi01_tmeslt1_on') [0:5] %}
          {% set slt1stop = states('input_datetime.id_switch_pifi01_tmeslt1_off') [0:5] %}
          {% set slt2en = is_state('input_boolean.ib_switch_pifi01_timeslot2_enable', 'on') %}
          {% set slt2start = states('input_datetime.id_switch_pifi01_tmeslt2_on') [0:5] %}
          {% set slt2stop = states('input_datetime.id_switch_pifi01_tmeslt2_off') [0:5] %}
          {% set slt1on = (slt1start <= time < slt1stop) if (slt1start < slt1stop) else (slt1start <= time or time < slt1stop) %}
          {% set slt2on = (slt2start <= time < slt2stop) if (slt2start < slt2stop) else (slt2start <= time or time < slt2stop) %}
          {% set tvon = is_state('binary_sensor.bs_media_tvlr', 'on') %}
          {% set tvlnk = is_state('input_boolean.ib_switch_pifi01_tvon_link', 'on') %}
          {{ ((slt1on and slt1en) or (slt2on and slt2en)) and not (tvon and tvlnk) }}
        friendly_name: Pi-Fi-01 Time Slot On

Then you use a simple automation to put the actual output switch ‘on’ AND ‘off’ : -

  - alias: au_switch_pifi01_onoff
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: binary_switch.bs_pifi01_timeslot_on
    action:
      - service_template: switch.turn_{{trigger.to_state.state}}
        entity_id: switch.switch_fibaro_f01

The problem is that this now generates an error (though it still works) : -
“Error while executing automation automation.au_switch_pifi01_onoff_template: Template rendered invalid service: switch.turn_”
I think what is happening is that at start up the templates are evaluated and as there is no actual trigger, the template gets resolved as “switch.turn_” rather than a valid service such as “switch.turn_on” or “switch.turn_off”
At a guess I’d suggest filtering possible errors against valid calls with valid triggering events.
Has anyone else noticed this behaviour ?

Reasons for doing this -
a) All logic in one place
b) Easy to test the binary sensor as you just paste the logic into the template editor
c) Test intemediary steps if necessary by adding ‘say’ {{ tvon }} or other variables as required

This has always generated an error at startup, since the beginning of time. There’s a number of ways you can block this. The simplest is to use 2 triggers.


    trigger:
      - platform: state
        entity_id: binary_switch.bs_pifi01_timeslot_on
        from: 'off'
        to: 'on'
      - platform: state
        entity_id: binary_switch.bs_pifi01_timeslot_on
        from: 'on'
        to: 'off'

or a condition validating the state

  - alias: au_switch_pifi01_onoff
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: binary_switch.bs_pifi01_timeslot_on
    condition:
    - condition: template
      value_template: >
      {{ trigger | default(none) is not none and trigger.to_state is defined and trigger.from_state is defined }}
    action:
      - service_template: switch.turn_{{trigger.to_state.state}}
        entity_id: switch.switch_fibaro_f01

Thanks,
I am combing the error logs a lot these days so may just have been blind to it previously.
Doubling the triggers may not help as the error will be from the action stage but I suppose that your point is that by defining the triggers this way then the action wont be evaluated until a trigger occurs, and the same with the condition.
I think I stole the original idea from you anyway so it makes sense you have a solition.
Still it does rob the automation of it’s elegant simplicity
Cheers

I’m puzzled by how that Template Binary Sensor’s template can produce anything other than true or false ( reported as on or off).

during startup the result is most likely none because any condition using none will return none. This is how python works.

{% set trues = [ True, 1, 1.111, "something" ] %}
{% set falses = [ False, 0, 0.0, "", None] %}
value| or| and
:-:|:-:|:-:|
{%- for t in trues %}
{{ t }}| {{ None or t }}|{{ None and t }}
{%- endfor %}

value| or| and
:-:|:-:|:-:|
{%- for t in trues %}
{{ t }}| {{ t or None }}|{{ t and None }}
{%- endfor %}

value| or| and
:-:|:-:|:-:|
{%- for t in falses %}
{{ t }}| {{ None or t }}|{{ None and t }}
{%- endfor %}

value| or| and
:-:|:-:|:-:|
{%- for t in falses %}
{{ t }}| {{ t or None }}|{{ t and None }}
{%- endfor %}

results:

Specifially note the left and right side of the and or or when values resolve true/false

i.e: {{ left or right}}, {{ left and right}}

None or/and True Value

value or and
True True None
1 1 None
1.111 1.111 None
something something None

True Value or/and None

value or and
True True None
1 1 None
1.111 1.111 None
something something None

None or/and False Value

value or and
False False None
0 0 None
0.0 0.0 None
None
None None None

False Value or/and None

value or and
False None False
0 None 0
0.0 None 0.0
None
None None None
3 Likes

Thanks for that! Now it’s easier to see how the template can produce an empty string.

1 Like