Skip to content

Instantly share code, notes, and snippets.

@EverythingSmartHome
Last active July 17, 2026 15:40
Show Gist options
  • Select an option

  • Save EverythingSmartHome/13f14c328669f72eee717752069a0398 to your computer and use it in GitHub Desktop.

Select an option

Save EverythingSmartHome/13f14c328669f72eee717752069a0398 to your computer and use it in GitHub Desktop.
A collection of useful templates for Home Assistant dashboards
{{ states.binary_sensor
| selectattr('attributes.device_class', 'in', ['door','window'])
| selectattr('state', 'equalto', 'on')
| list | count }}
{% set AREAS = ['kitchen','office','bedroom','living room'] %}
{% set DOMAIN = 'light' %}
{% set ns = namespace(ids=[]) %}
{% for a in AREAS %}
{% set ns.ids = ns.ids + area_entities(a) %}
{% endfor %}
{{ expand(ns.ids|unique)
| selectattr('domain','equalto', DOMAIN)
| selectattr('state','equalto','on')
| list | count }}
# Security 🔏
{% if states.sensor.open_doors_and_windows.state | int > 0 %}
You have {{states.sensor.open_doors_and_windows.state}} doors/windows open.
{% else %}
All windows and doors are closed.
{% endif %}
## Lights 💡
You have {{states.sensor.kitchen_light_count.state}} lights on currently.
{% set area_id = 'kitchen' %}
{% set ents = expand(area_entities(area_id)) %}
{% set lights = ents
| selectattr('domain', 'equalto', 'media_player')
| selectattr('state', 'equalto', 'playing') %}
{{ lights | list | count }}
{% set area_id = 'kitchen' %}
{% set ents = expand(area_entities(area_id)) %}
{% set switch = ents
| selectattr('domain', 'equalto', 'switch')
| selectattr('state', 'equalto', 'on') %}
{{ switch | list | count }}
{% set time = now().hour %}
{% if time >= 5 and time < 12 %}
{% set greeting = 'Good morning' %}
{% elif time >= 12 and time < 17 %}
{% set greeting = 'Good afternoon' %}
{% elif time >= 17 and time < 24 %}
{% set greeting = 'Good evening' %}
{% elif time >= 0 and time < 5 %}
{% set greeting = 'You should be sleeping' %}
{% endif %}
# {{greeting}}, {{user}}!
{% set time = now().hour %}
{% if time >= 5 and time < 12 %}
{% set greeting = 'Good morning' %}
{% elif time >= 12 and time < 17 %}
{% set greeting = 'Good afternoon' %}
{% elif time >= 17 and time < 24 %}
{% set greeting = 'Good evening' %}
{% elif time >= 0 and time < 5 %}
{% set greeting = 'You should be sleeping' %}
{% endif %}
{% if state_attr('calendar.lewis_s_calendar', 'start_time') == None %}
{% set cal_message = "you have no upcoming events, enjoy 🥳"%}
{% else %}
{% set start_time = state_attr('calendar.lewis_s_calendar', 'start_time') | as_timestamp | timestamp_custom("%H:%M", false) %}
{% set cal_message = "your next event is at " + start_time %}
{% endif %}
# {{greeting}}, {{user}}!
It's {{now().hour}}:{{now().minute}} and {{cal_message}}.
@theincubus

Copy link
Copy Markdown

If a door or window is open, it will share the name - it auto-finds all binary_sensors with device_class: door (and garage doors) and lists the ones that are on.

{% set open_doors = states.binary_sensor
| selectattr('attributes.device_class','in',['door','garage_door','opening'])
| selectattr('state','eq','on')
| list %}

{% if open_doors | count > 0 %}
{{ open_doors | count }} door(s) open:
{% for s in open_doors -%}

  • {{ s.name }}
    {%- endfor %}
    {% else %}
    All doors are closed.
    {% endif %}

If you want Windows too, then change the first line in the list to:
['door','garage_door','window','opening'] and replace the wording as you like.

@theincubus

Copy link
Copy Markdown

List the Thermostats that are turned on and their names.

{% set cooling = states.climate
| selectattr('state','eq','cool')
| list %}

{% if cooling | count > 0 %}
{{ cooling | count }} thermostat(s) in COOL mode:
{% for c in cooling -%}

  • {{ c.name }}{% if c.attributes.current_temperature is defined %} ({{ c.attributes.current_temperature }}°C){% endif %}
    {%- endfor %}
    {% else %}
    Turned off
    {% endif %}

@RSG-GIT

RSG-GIT commented Nov 18, 2025

Copy link
Copy Markdown

How can I include the lights I turn on with the Sonoff TX (switch) in this code? Thanks in advance for your help.

{% set AREAS = ['kitchen','office','bedroom','living room'] %}
{% set DOMAIN = 'light' %}

{% set ns = namespace(ids=[]) %}
{% for a in AREAS %}
{% set ns.ids = ns.ids + area_entities(a) %}
{% endfor %}
{{ expand(ns.ids|unique)
| selectattr('domain','equalto', DOMAIN)
| selectattr('state','equalto','on')
| list | count }}

@reubendowle

Copy link
Copy Markdown

The light-on count is watching ALL entities in the given areas changes which is not efficient. Better to filter the ns.ids to only the target domains:

{% set AREAS = ['garage','kitchen','alex bedroom','tessa bedroom','master bedroom','living room','office','guest bedroom','laundry'] %}
{% set DOMAIN = 'light' %}

{% set ns = namespace(ids=[]) %}
{% for a in AREAS %}
  {% set area_entities = area_entities(a) %}
  {% for entity_id in area_entities %}
    {% if entity_id.split('.')[0] == DOMAIN %}
      {% set ns.ids = ns.ids + [entity_id] %}
    {% endif %}
  {% endfor %}
{% endfor %}

{{ expand(ns.ids|unique)
    | selectattr('state','equalto','on')
    | rejectattr('entity_id', 'is_hidden_entity')
    | list | count }}

@fluffy88

Copy link
Copy Markdown

For the Light On Count template, if I wanted the count to work across all devices regardless of area, would this be a sensible template to use?

{{
  states.light 
    | selectattr('state','equalto','on') 
    | list 
    | count 
}}

@Homemf

Homemf commented Nov 19, 2025

Copy link
Copy Markdown

To add more areas, use this code and it works for me.

{% set AREAS = ['Kitchen', 'Office', 'Bedroom', 'Living Room'] %}
{% set DOMAIN = 'light' %}

{% set ns = namespace(ids=[]) %}

{# Recorre las áreas y busca entidades de varias formas para asegurar compatibilidad #}
{% for area in AREAS %}
{% set area_id = area | lower | replace(' ', '_') %}

{# Búsqueda normal por ID normalizada #}
{% set found = area_entities(area_id) %}

{# Fallback: usar atributos area_id de las entidades #}
{% if found | length == 0 %}
{% set fallback = states
| selectattr('attributes.area_id','equalto', area_id)
| map(attribute='entity_id')
| list %}
{% set found = found + fallback %}
{% endif %}

{# Último intento: usar el nombre tal cual (por si el area_id no está normalizado) #}
{% if found | length == 0 %}
{% set alt = area_entities(area) %}
{% set found = found + alt %}
{% endif %}

{# Acumular resultados #}
{% set ns.ids = ns.ids + found %}
{% endfor %}

{# Filtrar entidades del dominio (light, switch, etc.) y encendidas #}
{% set encendidas = expand(ns.ids | unique)
| selectattr('domain','equalto', DOMAIN)
| selectattr('state','equalto','on')
| list %}

{{ encendidas | count }}

@m24rwn

m24rwn commented Dec 11, 2025

Copy link
Copy Markdown

I would like to show doors open as a badge on home screen, just like the light count. I don’t want it to display if 0 doors are open. Anyone help with that ?

@jjlgit

jjlgit commented Jan 16, 2026

Copy link
Copy Markdown

the Markdown to display all open windows and doors outputs an error for me UndefinedError: 'None' has no attribute 'state'

@ifihaffto

Copy link
Copy Markdown

I would like to show doors open as a badge on home screen, just like the light count. I don’t want it to display if 0 doors are open. Anyone help with that ?

Exactly the same way.

Create a helper to do the count.

Add a condition to the Visibility of the tile and set 'above' to 0

@zombiehoffa

Copy link
Copy Markdown

The light-on count is watching ALL entities in the given areas changes which is not efficient. Better to filter the ns.ids to only the target domains:

@reubendowle man, that saved the day. took my home assistant from using 20 % cpu and 20 GB of ram and crashing intermittently and sluggish to fast again, using 3.9% cpu and 9 GB of ram. Thanks!

@Lieselchen

Copy link
Copy Markdown

I'd like to share a small change I made to the "light on count template"

In my version, I simply use all available areas via areas(). Since I don't have that many devices yet, iterating over the whole house is fine for my setup.

Most of my devices are connected via Zigbee2MQTT, and I added an availability check there. We sometimes turn off lights using the physical wall switch, which means Home Assistant may still think the light is "on" even though it is actually off.
Without the additional line, the counter is always wrong (in my case)

I also added the Line of @ccitro

For the Light On Count, you can exclude hidden entities like this ...
| rejectattr('entity_id', 'is_hidden_entity')

My updated Code:

{% set AREAS = areas() %}
{% set DOMAIN = 'light' %}

{% set ns = namespace(ids=[]) %}
{% for a in AREAS %}
  {% set ns.ids = ns.ids + area_entities(a) %}
{% endfor %}
{{ expand(ns.ids|unique)
   | selectattr('domain','equalto', DOMAIN)
   | selectattr('state','equalto','on')
   | rejectattr('entity_id', 'is_hidden_entity')
   | rejectattr('state', 'equalto', 'unavailable')
   | list 
   | count 
}}

@jraydoran

Copy link
Copy Markdown

Replacing line 21 of Welcome message with calendar event solves the issue where minute values < 10 are displayed as single integers with no leading 0:

It's {{ now().strftime("%H:%M") }} and {{ cal_message }}.

Thank you!

@jraydoran

Copy link
Copy Markdown

or state_attr('calendar.lewis_s_calendar', 'start_time') | as_datetime | as_local > today_at('00:00:00') %}

Thank you!

@Norkl

Norkl commented Jul 8, 2026

Copy link
Copy Markdown

For the Light On Count template, if I wanted the count to work across all devices regardless of area, would this be a sensible template to use?

{{
  states.light 
    | selectattr('state','equalto','on') 
    | list 
    | count 
}}

Bit late here, but I found this post that suggested using labels for the count. That works perfectly fine for me.

Added label "light" on all light entities and using this string I get a neat counter of all lights that are on in my home without needing to specify areas.

Template sensor helper:

{{ label_entities('light') | select('is_state','on') | list | count }}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment