Home Assistant: Templates
Here you find some Home Assistant template examples.
With these templates you can create new custom sensors based on other sensor values to use on the dashboard or in automations.
This new sensor can have a textual output or a boolean value true/false.
Table of Contents
- Home Assistant
- Template examples
- Is it a specific day in the year
- Count the number of lights on
- Calculate temperature differences
- Unavailable devices
- Low battery
- Floor activity
- Day of the week translation
- Trash bin days countdown
- Minutes since mail is delivered
- What to wear outside
- Calculate daylight brightness percentage
- Daylight brightness to opacity
- Is it night
- Expected rain amount
- Rain intensity
- CO2 threshold values
- Overlay based on lux
- Moon image based on state
- DIY Sink leak status
- DIY Chair occupancy status
Home Assistant
What is the difference between a binary and normal sensor?
A normal sensor can have any output, text, number or a boolean also and a binary sensor can only have a boolean value as output.
It can only have the state true
or false
.
This sensor can be used in automations to check if a condition matches.
How to add a template
There are two ways to add a template to your Home Assistant:
Via configuration.yaml
One way to add a new template is by adding the code to the configuration.yaml
file.
In 2022 the configuration for template entities changed. Where previously the configuration was placed under the sensor:
or binary_sensor:
section a new template
section was introduced.
Using the modern template format has a couple of advantages.
You can use a trigger
and action
(like in automations) which gives more control over when the entity should be updated, and it allows to set a state_class
so the state of the entity will also be stored in Long Term Statistics. It also allows to create button
, image
, number
and select
entities which is not possible using the legacy platform.
For more information also see the Home Assistant documentation. The legacy format is still documented all the way at the bottom.
All the examples below start with the template:
key. Be sure to define this only once in your configuration.yaml
. All template enitites should be created under the same template:
key.
Via the frontend
The other way is via the frontend, you can create a new template via the Settings menu item,
then go to Devices and Services and select Helpers.
This button directly opens the Helpers page in your Home Assistant:
Select the bottom-right button + CREATE HELPER
,
select Template then one of the two options Template a sensor or Template a binary sensor.
Copy the value_template
part from the below examples and add it in the visual editor under State template*.
In this example a (binary) template is created to check if the current month is August.
The template helpers are more user friendly to create, but lack some of the options the YAML configuration does, like templating the icon of the sensor, and working with triggers. It also doesn’t have the option to provide a template for availablity
of the entity.
How to debug a template
Via the Home Assistant frontend you can create and test a Template.
Go to the Developer tools menu item,
then go to Template tab.
Or use this button to open the Helpers in your Home Assistant:
Now you’re here:
In the Template editor the code can be placed and edit, and on the right you see direct the output.
Home Assistant use Jinja as a template engine to combine static text with variables.
Where to get help
Use the below examples, search the internet, use the Home Assistant Community forum, the HA Facebook groups, Reddit or ChatGPT to help you to create your own new templates.
The Home Assistant website contains also a lot examples!
ChatGPT is really useful and fast with helping you to create a new template and improve it to fine-tune it.
Template examples
Here are all kinds of different template examples.
Note that every entity has a unique_id
. This does not define the entity_id, the entity_id is defined by the name (so name: "Lights On"
will generate sensor.lights_on
).
By providing a unique_id
you will be able to change name
, icon
, entity_id
and based on the type of entity also the device_class
in the frontend.
It also ensures you don’t get suffixes like _2
after changing your configuration and reloading the template entities.
Is it a specific day in the year
A boolean sensor to test if it is a specific month, season, day (like Christmas or April Fools’ Day etc.)?
This will create binary_sensor
enties which will be on
when the template returns true
and otherwise they will be off
You can optionally refine the entities even more by providing a template for the icon
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- binary_sensor:
- name: "Is January"
unique_id: is_january
state: >
{{ now().month == 1 }}
- name: "Is Monday"
unique_id: is_monday
state: >
{{ now().isoweekday() == 1 }}
- name: "Is April Fools Day"
unique_id: is_april_fools
state: >
{{ now().month == 4 and now().day == 1 }}
- name: "Is Christmas"
unique_id: is_christmas
state: >
{{ now().month == 12 and now().day == 25 }}
- name: "Is around Christmas"
unique_id: is_around_christmas
state: >
{{ (now().month == 12 and now().day > 10) or (now().month == 1 and now().day < 11) }}
- name: "Is new years eve"
unique_id: is_new_years_eve
state: >
{{ now().month == 12 and now().day == 31 }}
Count the number of lights on
Count the number of lights with the status on
.
By checking if the entity_id
attribute exists on the light entities it will exclude the light groups created in Home Assistant.
Otherwise, it would count both the group, and the members as light, which will give a higher number than expected.
The icon is changed dynamically based on the state of the sensor itself, and self references the state using this.state
.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "# lights on"
unique_id: count_lights_on
icon: "{{ 'mdi:lightbulb' if this.state | int(0) > 0 else 'mdi:lightbulb-off' }}"
unit_of_measurement: "lights"
state: >
{{ states.light | rejectattr('attributes.entity_id', 'defined') | selectattr('state', 'eq', 'on') | list | count }}
Calculate temperature differences
Calculate the temperature difference between an inside room temperature and the outside temperature, and round by two decimals.
This sensor introduces an availability
template, which will ensure the template sensor will only be available when both source sensors are working properly.
If not, the template sensor will show as unavailable.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Temperature diff office and outside"
unique_id: template_diff_office_and_outside
icon: mdi:thermometer
unit_of_measurement: "°C"
state: >
{% set temp1 = states('sensor.espscd40_co2_temperature') | float %}
{% set temp2 = states('sensor.tempest_outside_temperature') | float %}
{{ (temp1 - temp2) | round(2, 'ceil') }}
availabilty: "{{ 'sensor.espscd40_co2_temperature' | has_value and 'sensor.tempest_outside_temperature' | has_value }}"
Unavailable devices
Get all devices by name that have the state unavailable in a sorted list.
As states are limited to 255 characters, the list is stored in an attribute, the state of the entity will be a count of the unavailable devices.
The device is considered unavailable when ALL entities belonging to that device are unavailable, as it could happen that only one entity is unavailable for specific reasons.
The icon is changed dynamically and will show the number of devices as well (9+ in case it’s over 9).
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Unavailable devices"
unique_id: count_unavailable_devices
state: " {{ this.attributes.get('devices', []) | count }}"
icon: >
{% set count = this.attributes.get('devices', []) | count %}
{{ 'mdi:numeric-9-plus-circle' if count > 9 else ('mdi:numeric-' ~ count ~ '-circle') }}
attributes:
devices: >
{% set devices = states
| map(attribute='entity_id')
| map('device_id')
| select()
| unique
%}
{% set ns = namespace(unavailable=[]) %}
{% for d in devices %}
{% set u = device_entities(d) | select('has_value') | list | count %}
{% if device_entities(d) | count > 0 and u == 0 %}
{% set ns.unavailable = ns.unavailable + [device_attr(d, 'name_by_user') or device_attr(d, 'name')] %}
{% endif %}
{% endfor %}
{{ ns.unavailable }}
Low battery
Get all devices by name that have the battery level with less than 10% in a sorted list.
It is not possible to simply filter on the state, as all states in Home Assistant are a string, and if you compare the string "6"
with the string "10"
you get unwanted results ("6" < "10"
returns false
).
Therefore, it is needed to convert the strings to a number first.
As we also still want to access the other properties, this requires a for-loop.
To access the data created in the for loop outside the for loop, a namespace has to be used.
Just like in the previous example, the names are listed in an attribute, because otherwise the character limit of 255 characters for an entity state can become an issue.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Low Battery Devices"
unique_id: count_low_batt_devices
state: " {{ this.attributes.get('devices', []) | count }}"
icon: >
{% set count = this.attributes.get('devices', []) | count %}
{{ 'mdi:numeric-9-plus-circle' if count > 9 else ('mdi:numeric-' ~ count ~ '-circle') }}
attributes:
devices: >
{% set threshold = 10 %}
{% set batt_sensors = states.sensor | selectattr('attributes.device_class', 'defined') | selectattr('attributes.device_class', 'eq', 'battery') | list %}
{% set ns = namespace(batt_low=[]) %}
{% for s in batt_sensors if s.state | float(101) <= threshold %}
{% set ns.batt_low = ns.batt_low + [device_attr(s.entity_id, 'name_by_user') or device_attr(s.entity_id, 'name') or s.name] %}
{% endfor %}
{{ ns.batt_low }}
Floor activity
Check if there is any activity on a specific floor or section based on multiple sensors.
One minute after the last trigger the state goes back to off
.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- binary_sensor:
- name: "Activity downstairs"
unique_id: activity_downstairs_sensor
state: >
{{ is_state("binary_sensor.motion1_occupancy", "on")
or is_state("binary_sensor.motion2_occupancy", "on")
or is_state("binary_sensor.motion3_occupancy", "on")
}}
device_class: occupancy
delay_off: "00:01:00"
Day of the week translation
By default, the day of the week is in English.
With this template, it translates the day to a non-English language (like here to Dutch).
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Day of week"
unique_id: day_of_week_sensor
icon: mdi:calendar
state: >
{{ ["maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag", "zondag"][now().weekday()] }}
Trash bin days countdown
Count the days before the paper bin will be picked up.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Paper Waste Pickup Countdown"
unique_id: paper_waste_pickup_countdown
icon: mdi:delete-empty
state: >
{% set pickup_date = strptime(state_attr('sensor.cyclus_papier','Sort_date'), '%Y%m%d') %}
{{ (pickup_date.date() - now().date()).days }}
unit_of_measurement: days
availability: "{{ strptime(state_attr('sensor.cyclus_papier','Sort_date', none), '%Y%m%d') is not none }}"
The sensor sensor.cyclus_papier
has an attribute Sort_date
which holds the date for the bin pickup day in the format “YYYYMMDD”.
Based on today’s date the diff in days is calculated.
(The sensor value is not always accurate, that’s why I use the attribute value.)
Minutes since mail is delivered
Minutes since the snail mail is delivered.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Mail Delivered"
unique_id: sensor_mail_delivered
state: >
{% set mailbox_datetime = states.binary_sensor.contact2_contact.last_changed %}
{{ (now() - mailbox_datetime).total_seconds() // 60 }}
icon: mdi:mailbox
unit_of_measurement: minutes
What to wear outside
Based on the outside temperature defined what to wear when you go outside.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Wear outside"
unique_id: sensor_wear_outside
icon: mdi:tshirt-crew
state: >-
{% set temp = states('sensor.tempest_temperature_feels_like_rounded') | float %}
{% if temp <= 5 %}
winter jacket and hand gloves
{% elif temp <= 14 %}
softshell
{% elif temp <= 18 %}
thin jacket
{% else %}
T-shirt
{% endif %}
availability: "{{ 'sensor.tempest_temperature_feels_like_rounded' | has_value }}
This is the code for the mushroom card, as shown on the image, based on this template.
# Sourcecode by vdbrink.github.io
# dashboard card code
type: custom:mushroom-chips-card
chips:
- type: entity
entity: sensor.what_to_wear_outside
icon: mdi:tshirt-v
Calculate daylight brightness percentage
Based on the sun sensor elevation and the cloud coverage, calculate the daylight brightness percentage. Which can be used to control the lights, the window blinds or on a floor map as overlay image.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Sunlight pct"
unique_id: sunlight_pct_sensor
state: >
{%- set elevation = state_attr('sun.sun','elevation') | float %}
{%- set cloud_coverage = states('sensor.dark_sky_cloud_coverage') | float %}
{%- set cloud_factor = (1 - (0.75 * ( cloud_coverage / 100) ** 3 )) %}
{%- set min_elevation = -6 %}
{%- set max_elevation = 90 %}
{%- set adjusted_elevation = elevation - min_elevation %}
{%- set adjusted_elevation = [adjusted_elevation,0] | max %}
{%- set adjusted_elevation = [adjusted_elevation,max_elevation - min_elevation] | min %}
{%- set adjusted_elevation = adjusted_elevation / (max_elevation - min_elevation) %}
{%- set adjusted_elevation = adjusted_elevation %}
{%- set adjusted_elevation = adjusted_elevation * 100 %}
{%- set brightness = adjusted_elevation * cloud_factor %}
{{ brightness | round }}
unit_of_measurement: '%'
device_class: 'illuminance'
Daylight brightness to opacity
Daylight brightness, from the previous template, converted to opacity for CSS to use as overlay on a floor map.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Sunlight Opacity"
unique_id: sensor_sunlight_opacity
state: >
{%- set sunpct = states('sensor.sunlight_pct') | float %}
{{ sunpct / 100 | float }}
Is it night
Boolean state if it is night. Will be on
when it’s night, otherwise it will be off
.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- binary_sensor:
- name: "Night State"
unique_id: binary_sensor_night_state
state: "{{ is_state('sun.sun', 'below_horizon') }}"
icon: "{{ 'mdi:weather-night' if is_state('sun.sun', 'below_horizon') else 'mdi:weather-sunny' }}"
Expected rain amount
Expected rain amount for the coming hours based on the Dutch Buienradar data.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Rain Expected"
unique_id: sensor_expected_rain
state: >
{% set rain = state_attr('sensor.neerslag_buienalarm_regen_data', 'data').precip %}
{{ rain | sum | round }}
unit_of_measurement: 'mm'
Rain intensity
Rain intensity for the coming hours based on the Dutch Buienradar data.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: Buienalarm Rain Level
icon: mdi:weather-pouring
state: >-
{% set threshold_light = '0.4' | float %}
{% set threshold_medium = '2.0' | float %}
{% set threshold_heavy = '5.0' | float %}
{% set rain = state_attr('sensor.neerslag_buienalarm_regen_data', 'data').precip[0] %}
{% if rain >= threshold_light %}
light rain
{% elif rain >= threshold_medium %}
medium rain
{% elif rain >= threshold_heavy %}
heavy rain
{% else %}
no rain
{% endif %}
CO2 threshold values
Create three static value sensors with the threshold values: 800, 1200 and 1500.
As the entity_id is based on the name
field, this template sensor uses a trick to give it the right name to base the entity_id on when the entity is created.
After that, the name will indicate the threshold name.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "{{ 'CO2 value 800' if this.state == 'unknown' else 'Good' }}"
unique_id: sensor_co2_value_800
state: 800
unit_of_measurement: "ppm"
- name: "{{ 'CO2 value 1200' if this.state == 'unknown' else 'Good' }}"
unique_id: sensor_co2_value_1200
state: 1200
unit_of_measurement: "ppm"
- name: "{{ 'CO2 value 1500' if this.state == 'unknown' else 'Good' }}"
unique_id: sensor_co2_value_1500
state: 1500
unit_of_measurement: "ppm"
It’s also possible to use a Number helper for this.
This generates an input_number.800
entity which can also be used in graphs.
It’s important to set here also the right unit of measurement.
Overlay based on lux
When you have a floor plan and want to show a dark overlay when the lux is low, you can create a new binary sensor based on the lux value.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- binary_sensor:
- name: "Overlay"
unique_id: sensor_overlay
state: "{{ states('sensor.motion_illuminance_lux') | float > 5 }}"
availability: "{{ 'sensor.motion_illuminance_lux' | has_value }}"
Moon image based on state
The default moon component in Home Assistant gives the moon phase as a text value. With an image corresponding to each phase, you can show the moon phase as an image.
Download here the moon images.
# Sourcecode by vdbrink.github.io
# configuration.yaml
# the template for the moon phase pictures using the original moon component
template:
- sensor:
- name: "Moon phase"
unique_id: sensor_moon_phase
state: "{{ states('sensor.moon') }}"
entity_picture: /local/moon_phases/{{ this.state }}.png
DIY Sink leak status
I created a custom leak sensor based on a contact sensor.
The used sensor stores the value if it detects a leak in an attribute value contact
.
This attribute is now used to create a boolean value.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- sensor:
- name: "Leak Sink"
unique_id: sensor_leak_sink
icon: mdi:water
state: >
{{ state_attr('binary_sensor.water_contact', 'contact') | lower }}
DIY Chair occupancy status
I created a custom chair occupancy sensor based on a contact sensor.
If you sit on it the contact sensor return off
.
The normal value of the contact sensor needs to be inverted.
That’s what happened here.
# Sourcecode by vdbrink.github.io
# configuration.yaml
template:
- binary_sensor:
- name: "Chair"
unique_id: binary_sensor_chair
state: >
{{ is_state('binary_sensor.contact1_contact', 'off') }}
device_class: presence
That’s it; I hope you can use some of these templates in your own setup.
Let me know which cool templates you use!
<< See also my other Home Assistant tips and tricks
Top | Homepage | Best Buy Tips