Display recently triggered automations

Goal

Display a list (in the UI) of all automations, sorted by last_triggered in reverse-chronological order (i.e. the most recently triggered automation appears first). Each row should display the automation’s name and the elapsed time since it was triggered (showing days, hours, and minutes).

Previous Solution

In the past I used the Auto-Entities Card to easily achieve the goal. A minor drawback is that the appearance is a bit cluttered because each row also shows an automation icon and a toggle button. I learned how to hide the unwanted widgets but it degraded the rendering performance (displaying the list went from sub-second to several seconds).

Current Solution

I now use the Markdown Card with the following Content:

|D|H|M||Name|
|----:|----:|----:|:--:|:----|
{% for state in states.automation
   |selectattr('attributes.last_triggered', 'defined')
   |selectattr('attributes.last_triggered')
   |sort(attribute='attributes.last_triggered', reverse=true) -%}
  {%- set t = now() - state.attributes.last_triggered -%}
  {%- set days = t.days if t.days > 0 else ' ' -%}
  {%- set hrs = t.seconds//3600 %}
  {%- set hrs = hrs if hrs > 0 else ' ' -%}
  |{{days}}|{{hrs}}|{{(t.seconds//60)%60}}||_{{state.name}}_|
{% endfor %}

The result is a Markdown table that renders very quickly and contains only the information I want.

Screenshot from 2021-03-11 12-36-22


EDIT

Added initial selectattr('attributes.last_triggered', 'defined') to only include automations that have a last_triggered attribute. Newly created automations that have never triggered lack a last_triggered attribute.

32 Likes

That’s VERY neat.

I just used (as in ‘used to use’) : -

{% for state in states.automation | selectattr('attributes.last_triggered') | sort(attribute='attributes.last_triggered', reverse=true) -%}
{{ state.attributes.last_triggered.timestamp() | timestamp_custom('%H:%M') }} : {{ state.name }}
{% endfor %}

In the template editor, I use this as a diagnostic when something happens unexpectedly I can check what probably caused it.
(But then I need to ensure that this is listed in the template editor of the device I’m using - (Double PITA ! ) )
But I REALLY like the idea of just being able to list this in a card.
Could we limit the output though (depending on peoples needs) to : -

  • A total number of lines (say 40 ???) ? or
  • A time period (say the last 12 hours ???) ?
1 Like

I’m doing something with pyscript and logging to a db table of all the service calls. It’s still very much a WIP, but I’m hoping to accomplish something similar to you, but including all service calls, not just automations.

Sure.

For example, if you only want the automations that triggered today, modify the for statement like this:

{% for state in states.automation
   |selectattr('attributes.last_triggered')
   |sort(attribute='attributes.last_triggered', reverse=true) 
   if (now() - state.attributes.last_triggered).days < 1 %}

If you do that then you will probably want to remove all the code that generates the first column in the table.

If you only want the automations that triggered in the past 12 hours (43200 seconds), change it to this:

{% for state in (states.automation
   |selectattr('attributes.last_triggered')
   |sort(attribute='attributes.last_triggered', reverse=true))
   if (now() - state.attributes.last_triggered).total_seconds() < 43200 %}

If you want to limit the number of lines to 20 then you can do it like this:

{% for state in (states.automation
   |selectattr('attributes.last_triggered')
   |sort(attribute='attributes.last_triggered', reverse=true))[:20] %}
13 Likes

I damn the fact that you can only use ‘1 like’ per per esteemed post.
10/10
A*
100%
:+1:

Cheers

2 Likes

@123 Taras, thanks very much for the card and the info on how to limit what is shown - very useful! I’ve made mine show the last three days, which is perfect for me. I appreciate your posting this! :star:

1 Like

Okay,
I Used Both (cutting it down to any automation last triggered in the last 24 hours AND the 40 off most recent (just to keep the card size to a manageable length - but this does mean it will vary quite a lot)) and played around with the formatting a bit.


I’m in two minds about listing the automations in Italics but I could remove the underscores at any time so I’ll keep it Italic for a while.
I prefer the actual ‘time’ the automation was triggered too.
Here’s the card entire : -

    ### Automations Triggered
    - type: markdown
      title: Automations Triggered
      content: |
        **Time &nbsp;&nbsp;&nbsp; Name**
        {% for state in (states.automation
          | selectattr('attributes.last_triggered')
          | sort(attribute='attributes.last_triggered', reverse=true)) [0:40] -%}
          {% if (now() - state.attributes.last_triggered).total_seconds() < 86400 %}
            {%- set t = (as_timestamp(state.attributes.last_triggered) | timestamp_custom('%H:%M', True)) -%}
            {{t}} &nbsp;&nbsp; _{{state.name}}_
          {% endif -%}
        {% endfor %}
2 Likes

I_c_u_prfr_abbrevtns :slightly_smiling_face:

1 Like

I think we have discussed this before (you referred to a rich Russian)
My naming conventions with a view to Quickly narrowing down lists and as used in VSC (autocomplete etc.) Means I waste space saying this automation is an automation and it can be found in my heating package and is sub-named ‘whatever’ means I have quick information on how to get at something.
The abvtns are there to claw back some real estate.
It works for me.
:man_shrugging: :smiley:

2 Likes

Taxonomic ordering; I use it as well but maybe not as consistently as I should.

1 Like

Using @Mutt 's code gives me the times in UTC, not my local time. How would I change them to be local time?

Edit: this post has been corrected

Is supposed to make the time into ‘local time’
What do you get in the template editor between the two ? i.e. : -

{{ as_timestamp(now()) | timestamp_custom('%H:%M', False) }}
{{ as_timestamp(now()) | timestamp_custom('%H:%M', True) }}

And is one, both or neither your local time ?

{{ states('sensor.time') }}

should also be your local time (but you need the time and date sensors set to use this)

1 Like

Thanks for your help! I tried both of those in the template editor - the first one (false) gives me UTC and the second one (true) gives me my local time.

{{ states('sensor.time') }} gives me my local time.

So is this working the opposite way for you?

That’s the way it’s designed to work.

From the documentation:

Filter timestamp_custom(format_string, local_time=True) converts an UNIX timestamp to its string representation based on a custom format, the use of a local timezone is default.

1 Like

I just tried the same for myself and ALL THREE give me local time.

Edit: I’m an idiot, I ‘guessed’ during testing and it gave me the correct times, I failed to note that I’m currently running on UTC anyway (another 16 days till the damned DST comes in)

My appologies, I’ll edit my post above

1 Like

Thanks, Taras, I was confused and thought @Mutt was saying that using false was supposed to give me local time. Still trying to bend my head around templating, I can usually figure out what someone else has written but still struggle to do it on my own :blush:

Thanks, Mutt, we’ve got it now :slightly_smiling_face: I’m working on a hybrid version of your card and Taras’, I am experimenting with having both the actual time and the elapsed time.

Thanks guys. I love when I come across stuff so great I have to add it immediately. I used to use an auto-entities card but It was never reliably showing all automations or updating as quickly as my automations would be triggering. Good stuff!

Here you go:

|D|H|M||Time||Name|
|---:|----:|----:|:--:|:---:|:--:|:----|
{% for state in states.automation
   |selectattr('attributes.last_triggered')
   |sort(attribute='attributes.last_triggered', reverse=true) -%}
  {%- set t1 = state.attributes.last_triggered.timestamp() | timestamp_custom('%H:%M') -%}
  {%- set t = now() - state.attributes.last_triggered -%}
  {%- set days = t.days if t.days > 0 else '&nbsp;' -%}
  {%- set hrs = t.seconds//3600 %}
  {%- set hrs = hrs if hrs > 0 else '&nbsp;' -%}
  |{{days}}|{{hrs}}|{{(t.seconds//60)%60}}||{{t1}}||_{{state.name}}_|
{% endfor %}

Feel free to modify it to suit your preferences.

4 Likes

Thanks, Taras, I didn’t expect/wasn’t asking for you to write it for me! You are a star :star: