Display recently triggered automations

I’m using this code that is still working on 2022.6.0 2022.6.2:

# Automations of the last 8 hours, but do not display more than 40 

        **Zeit      Name**
        {% for state in (states.automation
          | rejectattr('attributes.last_triggered', 'in', ['None', 'none', 'unknown'])
          | selectattr('attributes.last_triggered')
          | selectattr('state', 'ne', 'unavailable')
          | sort(attribute='attributes.last_triggered', reverse=true)) [0:40] -%}
          {% if state.attributes.last_triggered and (now() - state.attributes.last_triggered).total_seconds() < 28800 %}
            {%- set t = (as_timestamp(state.attributes.last_triggered) | timestamp_custom('%H:%M', true)) -%}
            {{t}} &nbsp;&nbsp; _{{state.name}}_
          {% endif -%}
        {% endfor %}

Thanks! I tried your code and got no output also. This is my formerly working code.

|H|M||Name|
|----:|----:|:--:|:----|
{% 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 %}
{%- 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;' -%}
  |{{hrs}}|{{(t.seconds//60)%60}}||_{{state.name}}_|
{% endfor %}

Copied your code into a Markdown Card and is working fine… strange.

for me on 2022.6.4 I am getting this error when trying it in the template editor

UndefinedError: ‘homeassistant.util.read_only_dict.ReadOnlyDict object’ has no attribute ‘last_triggered’

I don’t have the link at hand, but there is a bug in the template editor causing this in HA version 2022.6.

UPDATE: Template error in Template Editor while it works fine as custom template sensor · Issue #71360 · home-assistant/core · GitHub

You can try the suggestion in that report to filter on certain attributes being defined before using their values.

1 Like

The state of one of your automations is unknown (go to Developer Tools → States and confirm it) and so it doesn’t have a last_triggered attribute. The existing template doesn’t handle that situation gracefully.

I suggest you add a filter to select only automations that have a defined last_triggered attribute (it’s the same advice parautenbach offered).

{% for state in states.automation
 |selectattr('attributes.last_triggered', 'defined')
 |selectattr('attributes.last_triggered')
... etc ...
3 Likes

… add a filter to select only automations that have a defined last_triggered attribute (it’s the same advice parautenbach offered
^ IS the solution

Excellent, thank you!

Not sure if this is still working to date ? If so can someone post there working script?

The only significant modification to the original code was described on June 9 (three posts before your post). To prevent an error, it ensures it only references automations that have a last_triggered attribute.

If you want it to be very thorough about which automations are excluded/included, you can add the following three selectattr filters to the template:

{% for state in states.automation
 | selectattr('state', 'ne', 'unavailable')
 | selectattr('attributes.last_triggered', 'defined')
 | selectattr('attributes.last_triggered', 'ne', None)
  ... etc ...

Just wanted to say thank you to all of you for providing me this super tool, also for debugging.

Hi this isn’t working for me. I am running 2022.11.4 Core and get the error:
TypeError: '<' not supported between instances of 'str' and 'datetime.datetime'

The exact same code works fine for sensors though.
The following does work:

{{ states.automation
  | selectattr('attributes.last_triggered')
  | map(attribute='entity_id')
  | list  }}

I’m not sure if it is relevant, but when I ran the following, I got 2 different formats of timestamp back - one with a ‘T’ between date and time, and one without.

{{ states.automation
  | selectattr('attributes.last_triggered')
  | map(attribute='attributes.last_triggered')
  | list | join(', ')  }}

produces:

2022-11-27 09:14:34.558767+00:00,
2022-11-13T09:05:19.314270+00:00,

Any ideas?

Fwiw, I use a combination of the auto-entities-card with the multiple-entity-row which has the benefit of being able to directly go into the respective entity dialogue:

type: custom:auto-entities
card:
  type: entities
filter:
  include:
    - domain: automation
      last_triggered: <= 7d ago
      options:
        type: custom:multiple-entity-row
        secondary_info:
          attribute: last_triggered
          format: datetime
sort:
  method: last_triggered
  reverse: true

Hi folks,
I combined some of the ideas above to show automations and scripts (which may have been called by those automations).
Feel free to adjust how many items are to be used (curently 50 as per … “[:50]”) and how big the time window should be (curerntly 24h … as per " < 86400").

Br
/Fdo.

**Time &nbsp;&nbsp;&nbsp;&nbsp; Name**
{% set ns = namespace(a=[]) %}
{% set ns.a = (states.automation
  | selectattr('state', 'ne', 'unavailable')
  | selectattr('attributes.last_triggered', 'defined')
  | selectattr('attributes.last_triggered', 'ne', None)
  | selectattr('attributes.last_triggered')
  | sort(attribute='attributes.last_triggered', reverse=true)) -%}
{% set ns2 = namespace(s=[]) %}
{% set ns2.s = (states.script
   | selectattr('state', 'ne', 'unavailable')
   | selectattr('attributes.last_triggered', 'defined')
   | selectattr('attributes.last_triggered', 'ne', None)
  | selectattr('attributes.last_triggered')
  | sort(attribute='attributes.last_triggered', reverse=true)) -%}

{% for i in ns2.s %}
  {% set ns.a = ns.a + [i] %}
{% endfor %}

{%- for state in (ns.a | sort(attribute='attributes.last_triggered', reverse=true))[:50] -%}
  {%- if (now() - state.attributes.last_triggered).total_seconds() < 86400 %}
    {%- set t = (as_timestamp(state.attributes.last_triggered) | timestamp_custom('%H:%M:%S', true)) -%}
      {%- if state.entity_id.startswith("automation") -%}
      {{t}} - (a): _{{state.name}}_ 
      {%- else -%}
      {{t}} --- (s): _{{state.name}}_ 
      {%- endif %}
  {% endif -%}
{%- endfor -%}

1 Like

nice.

These are the ones I ended up using. I lay them out in a 2x2 grid using custom:grid-layout (hence the view_layout: grid-area: x) & happy to share that if anyone is interested).

- type: markdown
  view_layout:
    grid-area: a
  title: Automations last triggered today
  content: >
    <table>
    <tr>
      <th> Time </th>
      <th align=left> &nbsp Automation </th>
    </tr>
    {% for state in (states.automation
      | selectattr('attributes.last_triggered', 'defined')
      | rejectattr('attributes.last_triggered', 'in', ['None', 'none', 'unknown'])
      | selectattr('attributes.last_triggered')
      | selectattr('state', 'ne', 'unavailable')
      | sort(attribute='attributes.last_triggered', reverse=true)) [0:40] -%}
      {%- set time = state.attributes.last_triggered.timestamp() |timestamp_custom('%X')  -%}
      {%- if state.attributes.last_triggered > today_at("00:00") -%}
        {%- set t = (as_timestamp(state.attributes.last_triggered) | timestamp_custom('%H:%M', true)) -%}
        <tr align=left>
          <th> &nbsp {{time}} &nbsp </th>
          <td> &nbsp {{state.name}} </td>
        </tr>
        {% endif -%}
      {% endfor %}
    </table>
- type: markdown
  view_layout:
    grid-area: b
  title: Scripts last ran today
  content: >
    <table>
    <tr>
      <th> Time </th>
      <th align=left> &nbsp Automation </th>
    </tr>
    {% for state in states.script
      |selectattr('attributes.last_triggered')
      |sort(attribute='attributes.last_triggered', reverse=true) %}
      {%- set time = state.attributes.last_triggered.timestamp() |timestamp_custom('%X')  -%}
      {%- if state.attributes.last_triggered > today_at("00:00") -%}
        <tr align=left>
          <th> &nbsp {{time}} &nbsp </th>
          <td> &nbsp {{state.name}} </td>
        </tr>
        {% endif -%}
      {% endfor %}
    </table>
- type: markdown
  view_layout:
    grid-area: c
  title: Other Automations Last triggered
  content: >
    <table>
    <tr>
      <th> Days </th>
      <th> Date </th>
      <th> Time </th>
      <th align=left> &nbsp Automation </th>
    </tr>
    {% for state in (states.automation
      |selectattr('state', 'ne', 'unavailable')
      |selectattr('attributes.last_triggered', 'ne', None)
      |selectattr('attributes.last_triggered')
      |sort(attribute='attributes.last_triggered',reverse=true)) %}
      {%- set t = now() - state.attributes.last_triggered -%}
      {%- set date = state.attributes.last_triggered.timestamp() |timestamp_custom('%d/%m/%Y')  -%}
      {%- set time = state.attributes.last_triggered.timestamp() |timestamp_custom('%X')  -%}
      {%- if state.attributes.last_triggered < today_at("00:00") -%}
        <tr align=left>
          <td align=right> -{{t.days}} &nbsp </td>
          <th> {{date}} &nbsp </th>
          <td> &nbsp {{time}} &nbsp </td>
          <td> &nbsp {{state.name}} </td>
        </tr>
        {% endif -%}
      {% endfor -%}
    </table>
- type: markdown
  view_layout:
    grid-area: d
  title: Other scripts last ran
  content: >
    <table>
    <tr>
      <th> Days </th>
      <th> Date </th>
      <th> Time </th>
      <th align=left> &nbsp Script </th>
    </tr>
    {% for state in states.script
       |selectattr('attributes.last_triggered')
       |sort(attribute='attributes.last_triggered', reverse=true) %}
      {%- set t = now() - state.attributes.last_triggered -%}
      {%- set date = state.attributes.last_triggered.timestamp() |timestamp_custom('%d/%m/%Y')  -%}
      {%- set time = state.attributes.last_triggered.timestamp() |timestamp_custom('%X')  -%}
      {%- if state.attributes.last_triggered < today_at("00:00") -%}
        <tr align=left>
          <td align=right> -{{t.days}} &nbsp </td>
          <th> {{date}} &nbsp </th>
          <td> &nbsp {{time}} &nbsp </td>
          <td> &nbsp {{state.name}} </td>
        </tr>
        {% endif -%}
      {% endfor -%}
    </table>

edit: updated as accidentally posted an older version.

Is it possible to do the same for automations that succeeded/finished?

you can do all that in auto-entities, and the card is very simple

  - type: custom:auto-entities
    card:
      type: entities
      title: Recente Automaten
      show_header_toggle: false
    show_empty: false
    filter:
      include:
        - domain: automation
          state: 'on'
          last_triggered: '<= 5'

if you want to make it more complex ;-), add:

          options:
            type: custom:template-entity-row
            active: >
              {{is_state(config.entity,'on')}}
            toggle: true
            secondary: >
              {% if state_attr(config.entity,'last_triggered') %}
              {{relative_time(state_attr(config.entity,'last_triggered'))}} ago
              {% else %} Never triggered
              {% endif %}
            hold_action: |
              {
                "action": "navigate",
                "navigation_path": "/config/automation/trace/{{state_attr(config.entity,'friendly_name')}}"
              }

but… since we can have most of that directly in the Automations UI these days, and set any selector/order you need there, Ive personally moved all of these cards to the trash, and simply add a button that navigates to the automatons dashboard

2 Likes

Could you share your grid information you offered?

scroll up 3 posts :slight_smile:

This is exactly what I was looking for to keep an eye on if/when automations are running. Thanks for sharing.