Skip to content

Instantly share code, notes, and snippets.

@cameri
Last active January 3, 2026 22:12
Show Gist options
  • Select an option

  • Save cameri/1793ac7b9efc0c6e4a58eb815cadd9da to your computer and use it in GitHub Desktop.

Select an option

Save cameri/1793ac7b9efc0c6e4a58eb815cadd9da to your computer and use it in GitHub Desktop.
Home Assistant Blueprint: Stale sensor detection
blueprint:
name: Stale "Last seen" Sensor Report
description: >
Checks timestamp sensors ending in " Last seen". Lists those older than the threshold
or marked as "unavailable", stripping the suffix and adding the days ago.
domain: automation
input:
days_threshold:
name: Days Offline Threshold
description: Sensors older than this many days will be reported.
default: 7
selector:
number:
min: 1
max: 30
unit_of_measurement: 'days'
mode: slider
step: 1
time:
name: Time to test on
default: '08:00:00'
selector:
time: {}
exclude:
name: Excluded Entities
default: {entity_id: []}
selector:
target:
entity:
device_class: timestamp
actions:
name: Actions
description: '{{sensors}} will be replaced with the list (e.g., "Sensor Name (7d)").'
selector:
action: {}
variables:
days_threshold: !input 'days_threshold'
exclude: !input 'exclude'
threshold_seconds: "{{ days_threshold | int * 86400 }}"
sensors: >-
{% set result = namespace(sensors=[]) %}
{% set timestamp_sensors = states.sensor
| selectattr('attributes.device_class', 'defined')
| selectattr('attributes.device_class', 'eq', 'timestamp')
| list %}
{% for state in timestamp_sensors %}
{% if state.name.endswith(' Last seen') and not state.entity_id in exclude.entity_id %}
{% set clean_name = state.name | replace(' Last seen', '') %}
{% if state.state == 'unavailable' or state.state == 'unknown' %}
{# Handle unavailable sensors separately #}
{% set result.sensors = result.sensors + [clean_name ~ ' (unknown)'] %}
{% else %}
{# Calculate time difference for valid timestamps #}
{% set last_seen_ts = as_timestamp(state.state, 0) %}
{% set diff_seconds = as_timestamp(now()) - last_seen_ts %}
{% if diff_seconds > threshold_seconds %}
{% set days_ago = (diff_seconds / 86400) | int %}
{% set result.sensors = result.sensors + [clean_name ~ ' (' ~ days_ago ~ 'd)'] %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{{ result.sensors | join('\n') }}
trigger:
- platform: time
at: !input 'time'
condition:
- "{{ sensors != '' }}"
action:
- choose: []
default: !input 'actions'
mode: single
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment