How can I sort my motion sensors by last-changed?

I have an entities card listing my motion sensors (thanks konnected.io!) with secondary_info showing the last-changed state attribute, like so:

Is there any way to sort them, so the most recent motion one appears at the top?

Ideally I’d also like to style them a bit so any motion within say 5 minutes is bold or something. I don’t mind using custom cards.

Any suggestions?

Thanks

That’s not possible with the entities card, but you can use the home-feed-card for it.

@R_J Try using this Display which motion sensor triggered alarm in UI it works well for me.

1 Like

this looks like it fits the bill, thanks!

1 Like

It seems pretty solid in my use so far.

I created an input_text and an automation which “feeds” it with details about the last 5 motions like this:

input_text:
  last_motions:
    max: 255
    
automation:
  # Monitor motion sensors
  - alias: Monitor motion sensors
    trigger:
    - platform: state
      entity_id: 
      # motion sensors
      - binary_sensor.alarm_zone_2
      - binary_sensor.alarm_zone_3
      - binary_sensor.alarm_zone_4
      - etc
      # open-close sensors
      - binary_sensor.alarm_zone_1
      - binary_sensor.alarm_zone_5
      - binary_sensor.alarm_zone_7
      - etc
      to: 'on'
    action:
    - service: input_text.set_value
      target:
        entity_id: input_text.last_motions
      data:
        value: >-
          {% set newItem = trigger.to_state.last_changed.strftime('%H:%M:%S') + ' - ' + trigger.to_state.attributes.friendly_name %}
          {% set txt = states('input_text.last_motions') %}
          {% set strList = txt.split("|") %}
          {% set ns = namespace(newTxt=newItem) %}
          {% for item in strList %}
          {%   if loop.index < 5 %}
          {%     set ns.newTxt = ns.newTxt + "|" + item %}
          {%   endif %}
          {% endfor %}
          {{ ns.newTxt }}

At each motion event the event time and the motion sensor’s friendly name is inserted at the beginning of input_text.last_motions separated with a special character from the rest allowing to transform the string into a list of event-time - sensor-name pairs.

On the lovelace-UI the string is rendered using a markdown card like this:

- type: markdown
  title: Last five motions...
  content: "{{ states('input_text.last_motions') | replace('|', '\n') }}"

The markdown card could be combined with a conditional card which could display the markdown content only if the last_changed time of the input_text is not older than n minutes (implemented in a form of a template binary sensor).

1 Like

That’s a superb solution! In case of somebody is interested in getting the timezone correct as well for the triggers (as it’s UTC otherwise), just have the newItem defined as:
newItem = trigger.to_state.last_changed.astimezone().strftime('%H:%M:%S')

Meanwhile I simplified it (I removed the for statement, using a namespace to inject a variable from the outer scope is a little bit noisy)…
@tarmo - you are right, you should convert last_changed value to local

- service: input_text.set_value
  target:
    entity_id: input_text.last_motions
  data:
    value: >-
      {% set newItem = as_local(trigger.to_state.last_changed).strftime('%H:%M:%S') + ' - ' + trigger.to_state.attributes.friendly_name %}
      {% set txt = states('input_text.last_motions') %}
      {% set strList = txt.split("|")[:4] %}
      {% set txt = newItem + "|" + strList|join("|") %}
      {{ txt }}