Can I add new global python function to templates? If so, how?

In short

Some things are currently very tedious to do with templates. I want to add some high level Python functions to simplify them.

i.e. I want to be able to do this:

- service: light.turn_on
  entity_id: light.foo
  data_template:
    brightness_pct: "{{ my_custom_function() }}"
    color_temp: "{{ another_custom_function() }}"

Is there currently any way to add my own Python functions and make them globally available in templates?


One example of why I want this

I really don’t like what I have to do currently to change light levels based on time of day:

  - service: light.turn_on    
    entity_id: light.living_room_lights 
    data_template:              
      brightness_pct: >                  
        {% if now().hour <= 6 %}10          
        {% elif now().hour <= 15 %}100 
        {% elif now().hour <= 18 %}80 
        {% elif now().hour <= 20 %}50 
        {% elif now().hour <= 22 %}30  
        {% else %}10  
        {% endif %}   
      transition: 5

This is super verbose, confusing and it doesn’t actually change the light level smoothly based on the time, it changes in chunks with a long transition so I hopefully won’t notice.

I’m kind of surprised this isn’t already better supported in HA (at least I haven’t found any other solutions) so I want to write my own Python method where I can declaratively set my light preferences based on the current time.

I want to write a function that does that, something like this:

  - service: light.turn_on
    entity_id: light.living_room_lights
    data_template:
      brightness_pct: '{{
        time_based_value({
            "00:00": 1,
            "06:00": 1,
            "08:00": 100,
            "16:00": 100,
            "20:00": 50,
            "22:00": 20,
        })
      }}'
      transition: 1

This function would check the current time, then print a value right in between the previous time value and the next time value. For example, if the time was 07:00, the above function call would output “50”. If the time was 07:30, it would output “75” etc.

This would be much more Pythonic than using long if/else chains. It also has the advantage that the transitions can be much, much shorter, so the light responds much faster when turning auto control on/off, or turning the light on/off.

Since this time_based_value function doesn’t already exist, can I add it myself somewhere? Would it be as easy as adding it to the configuration somewhere, or would I need to jump through a lot of hoops like forking HA and adding it to the core?

Short answer: No.

Long answer: Only if you modify the source code for Home Assistant’s template helpers (i.e. adding it to core).


EDIT

Here’s an alternative to a long chain of if-elif:

What I do is that i have the brightness as an input_number, and then use various other automations to change that number - not only based on time of day, but also on the outside and inside background illuminance.
Then my “lights_on” automation use that input_number.

        - service: light.turn_on
          data_template:
            entity_id: light.living_room_lights
            brightness_pct: >
              {{ states('input_number.brightness_living_room') | float }}
2 Likes