Why doesnt this automation trigger automatically

getting back to this one more time, please have a look with me if it would be an option to check for the event state_changed on the attribute last_triggered?

these are the available events:

16

and last_triggered would account for a state change.

trigger:
    platform: event
    event_type: state_changed
    event_data:
      domain: automation
      attributes: last_changed

not sure about the attributes: last_changed of course since that isnt documented. But maybe it isnt necessary, for a triggered automation has its state changed…?

Interesting idea. Hadn’t thought of that.

FYI, the state_changed event is documented here.

Using that, this might work for you:

- alias: Automation ran
  trigger:
    platform: event
    event_type: state_changed
  condition:
    - condition: template
      value_template: >
        {{ trigger.event.data.entity_id.startswith('automation.') and
           trigger.event.data.entity_id != 'automation.automation_ran' and
           trigger.event.data.old_state is not none and
           trigger.event.data.new_state is not none }}
  action:
    - condition: template
      value_template: >
        {{ trigger.event.data.new_state.attributes.last_triggered !=
           trigger.event.data.old_state.attributes.last_triggered }}
    - ...

The reason I split the condition into two parts, one in the automation’s condition section, and the other in the automation’s action section, is that it’s possible for either trigger.event.data.old_state or trigger.event.data.new_state to be omitted None. Since the automation’s condition will always be evaluated, I wanted to avoid referencing something that might not exist (i.e., attributes...).

So, the first condition tests that the event is from the automation domain, and that it’s not from this automation itself. It also makes sure that both old_state and new_state exist are not None. Assuming all this is true, then the actions start to run.

The first action is a condition that decides if the new last_triggered is different from the old last_triggered. If so, then the automation must have just run. If not, then the rest of the automation actions don’t run.

I haven’t tested any of this, but based on my experience so far with HA, I think this might do what you want.

EDIT: This extremely old post has been brought back to haunt me. I’ve adjusted accordingly.

Nice, rebooting as i write… thx!

why wouldn’t we use the domain in the trigger directly? Wouldn’t that make it even more secure and processor friendly?

  trigger:
    platform: event
    event_type: state_changed
    event_data:
      domain: automation

can confirm the above doesnt work…

this though does:

- alias: Automation ran
  trigger:
    platform: event
    event_type: state_changed
  condition:
    - condition: template
      value_template: >
        {{ trigger.event.data.entity_id.startswith('automation.') and
           trigger.event.data.entity_id != 'automation.automation_ran' and
           'old_state' in trigger.event.data and 'new_state' in trigger.event.data }}
  action:
    - condition: template
      value_template: >
        {{ trigger.event.data.new_state.attributes.last_triggered !=
           trigger.event.data.old_state.attributes.last_triggered }}
    - service: notify.filed_automation_triggered
      data_template:
        message: "{{ trigger.event }}"
    - service: python_script.last_automation
      data_template:
        event: "{{ trigger.event }}"

got an automatic file creation with all notifications listed nicely, and the python script creates a sensor with the last automation in the frontend!

Magic, thank you very much!

1 Like

If you can figure out how to do that, then yes, that would be better. But I didn’t see that domain was one of the pieces of data in the event. Again, see here.

Where would you put the automation.count_warnings and automation.count_errors in these 2 to exclude them?

in the action template or in the condition?

If you mean you don’t want this automation to run when those two automations run, then in the automation condition part:

  condition:
    - condition: template
      value_template: >
        {% set skip_list = ['automation_ran', 'count_warnings', 'count_errors'] %}
        {{ trigger.event.data.entity_id.startswith('automation.') and
           trigger.event.data.entity_id.split('.')[1] not in skip_list and
           'old_state' in trigger.event.data and 'new_state' in trigger.event.data }}

no, the other way around…
I don’t want these two automations to be taken into account by the automation.automation_ran…but I think your skip list does just that? skip these automations from being a valid condition for the action?

other thing: right now, the {{trigger.event}} has this as a result per trigger:

2018-07-20T18:06:52.209329+00:00 <Event state_changed[L]: entity_id=automation.count_warnings, old_state=<state automation.count_warnings=on; last_triggered=2018-07-20T20:05:04.392134+02:00, id=Count warnings, friendly_name=Count warnings, custom_ui_state_card=state-card-custom-ui @

before, with my original automation, the event was:

2018-07-16T12:53:28.909974+00:00 2018-07-16 12:53:15.116120+00:00: automation Call Service Event (Script) was triggered

can i somehow change the {{trigger.event}} safely into
{{trigger.to_state.attributes.last_triggered}}: {{trigger.to_state.attributes.friendly_name}}

so it shortens the message somewhat?

Yes, that’s what I meant.

Not quite. Try:

{{ trigger.event.data.new_state.attributes.last_triggered }}
{{ trigger.event.data.new_state.attributes.friendly_name }}

But given that we’ve already checked that last_triggered just changed, and the state object has a name attribute that is the same as attributes.friendly_name (if there is one), you can shorten to:

{{ trigger.event.data.new_state.last_updated }}
{{ trigger.event.data.new_state.name }}
1 Like

thanks!
its really a lot of fun playing with these templates and scripts like this. My python script results in a much shorter message, based on the same {{trigger.event}}:

47

which is what I am trying to see in the notify log too.

for completeness sake this is the python:

pos_start = event.find('entity_id=')+21
pos_end = event.find(',', pos_start)

# Get the entity_id
#** entity_id = event[pos_start:pos_end]
entity_id = 'automation.' + event[pos_start:pos_end]

# get the state object
state = hass.states.get(entity_id)

# Make a time string in 24 hour format
#time_string = datetime.datetime.now().strftime('%I:%M')
dt = datetime.datetime.now() #state.attributes.get('last_triggered') #
time = "%02d:%02d:%02d" % (dt.hour, dt.minute, dt.second)
# try to get the automation friendly name
msg = []

try:
    msg = state.name
except:
    msg = None

if msg:
   if not msg.startswith('Set '):
       # Sensor update
       hass.states.set('sensor.last_automation', msg, {
#            'custom_ui_state_card': 'state-card-value_only',
#            'text': sensor_message,
            'unit_of_measurement': 'Aut',
            'friendly_name': time,
            'entity_picture': '/local/buttons/play-mode-repeat.png' })

much better! see before and after:

2018-07-20T21:12:49.847403+00:00 <Event state_changed[L]: entity_id=automation.update_last_motion, old_state=<state automation.update_last_motion=on; last_triggered=2018-07-20T23:12:47.772661+02:00, id=Update Last Motion, friendly_name=Update Last Motion, custom_ui_state_card=state-card-custom-ui @ 2018-07-20T20:25:02.643627+02:00>, new_state=<state automation.update_last_motion=on; last_triggered=2018-07-20T23:12:49.745384+02:00, id=Update Last Motion, friendly_name=Update Last Motion, custom_ui_state_card=state-card-custom-ui @ 2018-07-20T20:25:02.643627+02:00>>

2018-07-20T21:17:13.304607+00:00 2018-07-20 21:17:05.231622+00:00: Startup HA
2018-07-20T21:17:13.363184+00:00 2018-07-20 21:17:05.326261+00:00: Average indoor temp
2018-07-20T21:17:15.953688+00:00 2018-07-20 21:17:07.568440+00:00: Sense Switches change

time is 2 hours off though…and could be formatted more user friendly, as in the python. Would you know how to realize that final touch of finesse?

Where do you see this? I see these times:

2018-07-20T21:12:49.847403+00:00
2018-07-20T23:12:49.745384+02:00

They are (approximately) the same. It’s just that the first one is shown in UTC, whereas the second one is shown in local time. (I presume your local timezone is +02:00.)

in the screenshot i posted… There’s twice the time in etc, not local time??
2018-07-20T21:17:15.953688+00:00 2018-07-20 21:17:07.568440+00:00: Sense Switches change

this is what im getting back from the template, and yes, we are +2 hours from etc…

The log timestamps (the date/times at the beginning of each line) do look like they’re printed in UTC. I see the same in my log file. However, if the output of a template is showing a time in UTC (+00:00) and you’d rather show it in local time (+02:00), you can definitely do that. But exactly how you do that depends on what type the data really is (i.e., string or Python datetime), which may not be obvious. But what usually works is:

{{ as_timestamp(whatever)|timestamp_local }}

thank you, trying this next:

message: >
 {{ as_timestamp(trigger.event.data.new_state.last_updated)|timestamp_local }}: {{ trigger.event.data.new_state.name }}

resulting in:

2018-07-21T09:54:53.938134+00:00 2018-07-21 11:54:44: Call Service Event (Script)
2018-07-21T09:55:08.208271+00:00 2018-07-21 11:55:00: Call Service Event (Script)
2018-07-21T09:55:09.870117+00:00 2018-07-21 11:55:03: Call Service Event (Script)
2018-07-21T09:55:10.188106+00:00 2018-07-21 11:55:03: Sense Active change
2018-07-21T09:55:12.629398+00:00 2018-07-21 11:55:08: Sense Active change
2018-07-21T09:55:12.656599+00:00 2018-07-21 11:55:09: Sense Active change
2018-07-21T09:55:13.569690+00:00 2018-07-21 11:55:10: Sense Active change
2018-07-21T09:55:15.674322+00:00 2018-07-21 11:55:13: Call Service Event (Script)
2018-07-21T09:55:22.950335+00:00 2018-07-21 11:55:22: Sense Active change
2018-07-21T09:55:23.889922+00:00 2018-07-21 11:55:23: Sense Active change
2018-07-21T09:55:25.255489+00:00 2018-07-21 11:55:24: Call Summary

id say, almost there… now how to only show the last bit, from the local time 2018-07-21 11:55:24: Call Summary, maybe even the time part, cause the date is rather superfluous here.

If you want just the time (and now that I know you’re working with a datetime), you can do this:

{{ trigger.event.data.new_state.last_updated.strftime('%H:%M:%S') }}

As far as removing the first date/time on each line, I guess I’m not sure of the complete context here. Are these going into your HA log? If so, I think the logging system automatically outputs that. Honestly, I’d probably have to do a lot of digging to figure that out, even once I knew the context.

no these are going into the file through the notify.file https://www.home-assistant.io/components/notify.file/:

service: notify.filed_automation_triggered

creating the filed_automation_triggered.txt in the config directory, listing all triggered automations

Right on that page is the answer. :wink: Use the optional timestamp parameter and set it to False.

tis is not it…

before:
2018-07-21T13:16:59.750487+00:00 2018-07-21 15:16:59: Sense Active change
after:
2018-07-21T13:20:44.140325+00:00 13:20:34: Startup HA

Aha, so the timestamp=true renders the utc time… and I thought it was so easy using that…false it is!

Apparently the default is false. And I just verified that looking at the code. So you could just simply remove that parameter from your configuration.

1 Like