Logic, Math, & More


This page is a collection of other template examples demonstrating the use of basic logic and other template based operations.


This template creates a sensor to determine whether a space is occupied or not. It receives input from two motion sensors, the on/off state of a TV, and tracks the time since any of these items last changed state. The space is deemed “Occupied” if any device is “on” or if no more than three minutes has elapsed since the state of a device was last changed. This sensor state is then used as an input to control other things like lights, a ceiling fan, and heating in the referenced space. It utilizes: a max filter, the “in” operator, & if/then logic.

- platform: template
  sensors:
    office_occupancy:
      friendly_name: Office Occupancy
      value_template: >
        {% set motion1 = states("binary_sensor.office_motion_sensor_motion") %}
        {% set motion2 = states("binary_sensor.aeotec_trisensor2_motion") %}
        {% set tv_state = states("media_player.office_tv") %}
        
        {% set t = as_timestamp(now()) | float() %}
        {% set motion1_last_changed = as_timestamp(states.binary_sensor.office_motion_sensor_motion.last_changed) |float() %}
        {% set motion2_last_changed = as_timestamp(states.binary_sensor.aeotec_trisensor2_motion.last_changed) | float() %}
        {% set tv_last_changed = as_timestamp(states.media_player.office_tv.last_changed) | float() %}
        {% set time_since_last_change = t - ([motion1_last_changed, motion2_last_changed, tv_last_changed] | max)  %}        
    
        {% if "on" in [motion1, motion2, tv_state] or time_since_last_change < 180 %}
          Occupied
        {% else %}
          Unoccupied
        {% endif %}


I live close enough to the coast that we sometimes go to the beach. When we do, I like to know where the tide is in relation to the day’s high/low levels. Pulling the high/low data along with the associated times is straightforward with the NOAA tide custom integration (listed on this page), if you just want the tide directionality. But some additional work is needed to get where the tide is now. Templates can help with that. The template block below creates two sensors. The first calculates the tidal change between the next_tide_level and the last_tide_level. This result is then used in the second sensor along with a tide factor (it’s really a time factor treated as a percentage), to compute the current tide level.* For example, if the next_tide_level is at the eight foot mark and the last_tide_level was at the 2 foot mark, and we’re exactly halfway in time between the last and next tide events, then the current tide is at the five foot mark (2+(6*.5)), with three feet remaining to go until the next tide at eight feet.

- platform: template
  sensors:
    tide_change:
      friendly_name: "Tide Change"
      value_template: >
                    {{ (states('sensor.next_tide_level') | float(0) - states('sensor.last_tide_level') | float(0)) }}
      icon_template: "{% if is_state_attr('sensor.tides', 'next_tide_type', 'High') %}mdi:arrow-top-right{% else %}mdi:arrow-bottom-right{% endif %}"
      unit_of_measurement: 'ft'

    tide_level_now:
      friendly_name: "Tide Level"
      value_template: >
        {% if is_state_attr('sensor.tides', 'next_tide_type', 'High') %}
          {{ (states('sensor.last_tide_level') | float(0)) + ((states('sensor.tide_change') | float(0)) * (state_attr('sensor.tides', 'tide_factor') | float(0) / 100)) }}   
        {% else %}
          {{ (states('sensor.last_tide_level') | float(0)) + ((states('sensor.tide_change') | float(0)) * (1 - state_attr('sensor.tides', 'tide_factor') | float(0) / 100)) }}
        {% endif %}        
      icon_template: "{% if is_state_attr('sensor.tides', 'next_tide_type', 'High') %}mdi:arrow-top-right{% else %}mdi:arrow-bottom-right{% endif %}"
      unit_of_measurement: 'ft'

* A more accurate calculation method would be to use ‘The Rule of Twelfths,’ which is overkill for this average beach goer. Still, I may implement it at some point, if only to see it work.


Here’s a quick snippet to drop into the template editor (under your_HA_URL:8123/developer-tools/template) to see a list of ALL the entities you have created (…and their current states) in your Home Assistant instance.

  {%- for state in states -%}
    {{state.entity_id}}
  {% endfor %}

  {% for state in states.sensor %}
    {{ state.entity_id }}={{ state.state }},
  {% endfor %}


… in case a currency format is needed, ex. $10.00

- platform: template
  sensors:
    weekly_allowance: 
      friendly_name: "allowance"
      value_template: >-      
        {% set amt = states("input_number.allowance_total") | float() %}
        {% if amt >0 %}
          {% set total = amt %}
        {% else %}
          {% set total = 0 %}
        {% endif %}
        {{ '${:,.2f}'.format(float(total)) }}