What trigger data to use when using a template trigger?

Well, I must have had a “senior moment” last night when I went to bed because I completely forgot to set my alarm to get up for work this morning and to put my phone on the charger like I do every night. :older_man:

So, I got to thinking, since I already have a work calendar set up and I have my phone alarm status all coming in to HA why not automate my Echo to remind me around the time I usually go to bed that I don’t have an alarm set if I have to go to work the next day. Isn’t HA awesome! :laughing:

I set up a boolean to indicate if my alarm is not actually set if it should be and it’s correctly turned on by the followimg automation:

- alias: Set My Phone Alarm Needed Bool
  trigger:
    - platform: template
      value_template: >
        {% if is_state('sensor.my_mobile_app_next_alarm', 'unavailable') and ( is_state_attr('calendar.my_gmail_com', 'message', 'days') or is_state_attr('calendar.my_gmail_com', 'message', 'DD - support') ) %}
          true 
        {% else %}
          false 
        {% endif %}
  action:
    - service: input_boolean.turn_on
      entity_id: input_boolean.my_phone_alarm_needed_but_not_set

But if I set the alarm I want the boolean to also get turned back off.

I tried to use the trigger data to turn it on/off as appropriate like this:

  action:
    - service: >
        {% if trigger.to_state.state == 'true' %}
          input_boolean.turn_on
        {% else %}
          input_boolean.turn_off
        {% endif %}
      entity_id: input_boolean.my_phone_alarm_needed_but_not_set

But it didn’t work.

I don’t think I’ve ever seen the trigger data from a template trigger used in the service call. According to the docs it implies my trigger data should work. But in thinking about it logically the trigger needs to go from true to false then back to true again for the automation to actually trigger. And if the automation doesn’t trigger then there is no trigger data to check the new “to_state” so of course it wouldn’t do anything at all. It doesn’t even work when the trigger is satisfied (template goes from false to true) and the automation is actually triggered. So it doesn’t look like even then there is an available “to_state” to satisfy the “if” and run the turn_on service…

So I’m not sure if I’m doing something wrong and/or thinking about it wrong or if the docs are misleading.

The black box of the “trigger” object is very hard (if not impossible) to troubleshoot since you can’t see what’s going on behind the scenes. Or at least I don’t know of a way to see it.

I’ve got it working fine using two automations (one to turn it on & another to turn it off) but if nothing more than for an educational opportunity I’d like to know how to correctly set up the service call in this situation if it’s even possible.

TIA.

Surely if it is a template trigger, it, ummm, only triggers when the template is, ummm, true…

Right.

That’s what I was thinking but the docs say there is a trigger object that can be used from a template:

TEMPLATE

Template variable Data
trigger.platform Hardcoded: template
trigger.entity_id Entity ID that caused change.
trigger.from_state Previous state object of entity that caused change.
trigger.to_state New state object of entity that caused template to change.
trigger.for Timedelta object how long state has been to state, if any.

That’s why I was saying the docs seem to be misleading. I just needed another brain to support that thought.

Yah, the most recent state that changed is passed into to_state. So in your template, if sensor.my_mobile_app_next_alarm was the last sensor to cause the trigger, that will come through in the to_state.

EDIT: To clarify further, the true/false never gets passed. Just as @anon43302295 says below, the template triggers only continue when it resolves true.

1 Like

No, I mean that the action never runs when the template is false (because it only triggers on true), so your service template never runs.

You probably don’t need a template trigger at all for that, a state trigger will do it:

- alias: Set My Phone Alarm Needed Bool
  trigger:
    - platform: state
      entity_id: sensor.my_mobile_app_next_alarm
  action:
    - service: >
        {% if trigger.to_state.state == 'unavailable' %}
          input_boolean.turn_on
        {% else %}
          input_boolean.turn_off
        {% endif %}
      entity_id: input_boolean.my_phone_alarm_needed_but_not_set

That will turn the input_boolean on"if the sensor goes to “unavailable” and off when it changes to anything else.

But the service template should run if the trigger template returns true and the to_state of the trigger is ‘true’.

I agree it shouldn’t run if the to_state of the trigger is false.

However, I think that @petro is onto something tho. I’m using ‘to_state == true’ & ‘to_state == false’ but if the phone app is the last thing that changes to activate the trigger and that is what the trigger object is looking at for the state then the state isn’t true or false, it’ll be “unavailable” or some datetime.

Let me try that and I’ll get back to you.

create a persistent notification and just output the whole trigger object as the message

 message: "{{ trigger }}"

Then look at it in your notifications.

1 Like

If I am only looking at my alarm status that would be correct but I also only need/want to set an alarm if I have to get up the next day for work. So I need to check the calendar attribute to see if the next day is a work day. For that I need the template. I might be able to do it with conditions but either way I need some check of the calendar somewhere.

ooh, that’s good. I’l, try it.

OK, based on the results of the persistent notification:

{‘platform’: ‘template’, ‘entity_id’: ‘sensor.my_mobile_app_next_alarm’, ‘from_state’: <state sensor.my_mobile_app_next_alarm=2020-11-01T12:40:01.000Z; Local Time=Sun Nov 01 07:40:01 EST 2020, Package=com.sec.android.app.clockpackage, Time in Milliseconds=1604234380000.0, friendly_name=My Mobile App Next Alarm, icon=mdi:alarm, device_class=timestamp @ 2020-10-31T13:47:36.980815-04:00>, ‘to_state’: <state sensor.my_mobile_app_next_alarm=unavailable; Local Time=, Package=, Time in Milliseconds=0.0, friendly_name=My Mobile App Next Alarm, icon=mdi:alarm, device_class=timestamp @ 2020-10-31T13:47:42.382314-04:00>, ‘for’: None, ‘description’: ‘sensor.my_mobile_app_next_alarm via template’}

I tried both:

- alias: Set My Phone Alarm Needed Bool
  trigger:
    - platform: template
      value_template: >
        {% if is_state('sensor.my_mobile_app_next_alarm', 'unavailable') and ( is_state_attr('calendar.my_gmail_com', 'message', 'days') or is_state_attr('calendar.my_gmail_com', 'message', 'DD - support') ) %}
          true 
        {% else %}
          false 
        {% endif %}
  action:
    - service: persistent_notification.create
      data:
        message: '{{trigger}}'
    - service: >
        {% if trigger.to_state.state == 'unavailable' %}
          input_boolean.turn_on
        {% else %}
          input_boolean.turn_off
        {% endif %}
      entity_id: input_boolean.my_phone_alarm_needed_but_not_set

and then changed just the second service call to:

- service: >
    {% if trigger.to_state.state == 'sensor.my_mobile_app_next_alarm=unavailable' %}
      input_boolean.turn_on
    {% else %}
      input_boolean.turn_off
    {% endif %}
  entity_id: input_boolean.my_phone_alarm_needed_but_not_set

I know the trigger is working since it created the persistent notification but neither worked to turn the boolean on when the trigger returned true so I’m not sure exactly what the format should be for to_state.

I think the problem is that, since this is a template trigger, it will be triggered by a change in any of the entities used in the trigger. The trigger properties are based on whatever changed to cause the trigger to fire, which could be the alarm sensor but could also be the calendar events.

You’d need to hard code the template in the action to use sensor.my_mobile_app_next_alarm.state instead of trigger.to_state.state to make sure it always uses the alarm sensor instead of whatever else may have caused the trigger to fire.

You’d still have the issue that the trigger will only ever fire when the value_template returns true, so the logic in the action for turning off the input_boolean will never run.
You would need to either come up with a template which would return true if either the input_boolean needs to be turned on or off, or maybe split it into a separate trigger (maybe just a time trigger so runs once a day or a state trigger on the alarm sensor) and condition (on the calendar).

1 Like

Since the actual ultimate action I want to perform is to make a TTS announcement at a certain time I think I’ve decided to rework it to use the time as a trigger and then use the above previous trigger template as a condition.

That way I reduce the number of automations to only one and eliminate the need for the boolean completely…I think…I haven’t done it yet but that’s my thought.

However the question still remains what is the correct syntax to use the “to_state” of the sensor from the trigger object as posted above? I’ve tried it a few ways that I thought might work in the template editor but I can’t ever get it to give the expected results.

Again just as an educational opportunity. It might come in handy at some point for someone.

Normally trigger.state.to_state would be the correct syntax to use to get the state this always picks up the state which ultimately caused the trigger to fire. For example, with this example:

trigger:
  - platform: template
    value_template: >-
        {{ is_state("sensor.sensor_one", "on") or is_state("sensor.sensor_two", "on") }}

trigger.state.to_state will return the state of either sensor.sensor_one or sensor.sensor_two, depending on which one changed to on most recently and triggered the automation.

As far as I know from checking the documentation, there’s no way from the trigger object to pick up the states used in the trigger. The same would apply if you have multiple triggers. So, if you want to do this, you would need to hard code the entities in your action rather than rely on the trigger object.

I agree that this should work but it doesn’t seem to in this case (actually looking at it again I think you meant to write “trigger.to_state.state” but I get what you mean…unless I’m missing something again?).

In my last automations I posted above (and based on my trigger object info I also copied into the same post) neither of those two versions worked to call the “input_boolean.turn_on” service.

And the only one of the entities that is changing is the phone alarm sensor which is reflected in the data from the persistent notification (which is fired by the same trigger). The calendar sensor only changes once a day and I can trigger the automation by just turning my alarm on & off.

So relating that to your example “sensor.sensor_one” would be the only entity to change.

Maybe I’m just being dense and not getting something obvious so thanks for sticking with me on this.

It’s possible that newlines in the template in the action are causing issues. If that is the issue, doing it like this should help:

- service: >-
    {%- if trigger.to_state.state == 'unavailable' -%}
      input_boolean.turn_on
    {%- else -%}
      input_boolean.turn_off
    {%- endif -%}
  entity_id: input_boolean.my_phone_alarm_needed_but_not_set

The >- and using {%- and -%} instead of just {% and %} will ensure that any newlines are stripped out.

Edit: Or alternatively, like this which avoids the if and endif entirely:

- service: >-
    {{ "input_boolean.turn_on" if trigger.to_state.state == 'unavailable' else "input_boolean.turn_off" }}
  entity_id: input_boolean.my_phone_alarm_needed_but_not_set

tried both and neither worked.

EDIT to add:

I’ve also checked the home-assistant.log and there’s nothing in there either.

I wrote a simple automation and it works as I would expect… I noticed that the trigger needs to go from false to true to trigger. It will not trigger from a true -> true transition. So in my automation case below, I need to have my input_boolean off, and my input_number below 20 to turn the template to false.

alias: New Automation
description: ''
trigger:
  - platform: template
    value_template: "{{ states('input_number.test') | int > 20 or is_state('input_boolean.wait_for_trigger','on') }}"
condition: []
action:
  - service: persistent_notification.create
    data:
      message: >
        {{ trigger.entity_id }}
        {% if trigger.entity_id == 'input_number.test' and trigger.to_state.state | int > 25 %}
          ABOVE 25
        {% elif trigger.entity_id == 'input_boolean.wait_for_trigger' %}
          WAIT_FOR_TRIGGER
        {% else %}
          BETWEEN 20 and 25
        {% endif %}
mode: single

so in your case, I would expect this to work (I took the liberty of simplifying your template). It’s not much different from what you have currently.

- alias: Set My Phone Alarm Needed Bool
  trigger:
    - platform: template
      value_template: >
        {{ is_state('sensor.my_mobile_app_next_alarm', 'unavailable') and ( is_state_attr('calendar.my_gmail_com', 'message', 'days') or is_state_attr('calendar.my_gmail_com', 'message', 'DD - support') ) }}
  action:
    - service: >
        {% if trigger.to_state.state == 'unavailable' %}
          input_boolean.turn_on
        {% else %}
          input_boolean.turn_off
        {% endif %}
      entity_id: input_boolean.my_phone_alarm_needed_but_not_set

Things to note, in order for this to trigger, this needs to move from false to true.

Resting State prior to trigger

In order to be in a false state, your entities need to have the following states:

entity attribute value
sensor.my_mobile_app_next_alarm state ‘unavailable’
calendar.my_gmail_com message anything but ‘days’ or ‘DD - support’

or

entity attribute value
sensor.my_mobile_app_next_alarm state anything but ‘unavailable’
calendar.my_gmail_com message ‘days’ or ‘DD - support’

or

entity attribute value
sensor.my_mobile_app_next_alarm state anything but ‘unavailable’
calendar.my_gmail_com message anything but ‘days’ or ‘DD - support’

To Trigger

To turn on input_boolean.my_phone_alarm_needed_but_not_set, the state would need to be:

trigger entity: sensor.my_mobile_app_next_alarm

entity attribute value
sensor.my_mobile_app_next_alarm state ‘unavailable’
calendar.my_gmail_com message ‘days’ or ‘DD - support’

To turn off input_boolean.my_phone_alarm_needed_but_not_set, the state would need to be:

trigger entity: calendar.my_gmail_com

entity attribute value
sensor.my_mobile_app_next_alarm state ‘unavailable’
calendar.my_gmail_com message ‘days’ or ‘DD - support’

Confusing right??? This is because the template switches between the 2. So if your trigger entity is the calendar, the input boolean will always turn off. If your trigger entity is the sensor, it will turn on.

the only entity that has ever changed in my testing has been the phone alarm status changing from “unavailable” to some other time value. The calendar state has always stayed the same (‘days’).

I believe that the trigger is indeed changing from false to true when I set an alarm (not ‘unavailable’) then subsequently turn the alarm off (‘unavailable’). The reason I believe this is that the persistent notification is sent every time I turn off the alarm. So the trigger really is working.

The part that doesn’t seem to be working is the service call template to turn the boolean to (at least) ‘on’ (I realize now that the turn off service would never have been called but that’s another issue that’s been fixed).

I don’t get why the template fails to ever return true for the trigger.to_state.state syntax I’m using.

After I wrote all of that I used your simplified automation and suddenly it worked! :astonished:

So I thought that trigger can’t have been the cause since I’ve used that syntax before in conditions when the simpler single line didn’t seem to work. So I copied my latest complex trigger from the above post and it still worked!

So I thought maybe I had a typo somewhere in the original automation that I posted in my initial post so I copied that back in and that one worked now too! Of course, I had to change the trigger.to_state test from ‘true’ to ‘unavailable’… But it worked…

Now I’m totally confused about why the initial change from ‘true’ to ‘unavailable’ didn’t work.

The only thing that has changed since yesterday is that the “message” attribute changed from ‘days’ to ‘nights’ and I have that updated in all of the automations to test it.

Surely that couldn’t have been the issue. It’s not like it’s easy to have a typo in ‘days’. :roll_eyes:

:man_shrugging: I literally have no idea what the hell was happening before that isn’t now…

But the solution to the original question was in petro’s first post and i needed to use the last changed entity state data.

Thanks to everyone for sticking this out and I’m really sorry that I ended up wasting peoples time for some unknown anomaly. I’m actually embarrassed by this. :flushed: