Templating custom filters

Home Assistant’s custom template macros only support returning strings. Therefore, you would have to use additional filters and hacks to convert to other types (lists, dictionaries, boolean, numbers, etc). Whereas this custom_filters component allows you to work with and return various data types.

Yes, but most of those filters aren’t even needed… They just replicate existing functionality. Not to mention, that custom lib loads things incorrectly. Lastly, macros only return strings, but set variables return native types.

I definitely use all of those filters, but that’s my personal configuration and setup.

Please feel free to submit a PR on GitHub if you would like to contribute!

I always just add the filters directly into core, no reason to make a custom lib when you can just build it right in for everyone.

I have built a “natsort” filter so that numbers and strings with numbers are sorted properly. I added it to helpers/template.py to home assistant core.
Example:
{{ states.sensor|natsort(attribute="state")|map(attribute="state")|list }}
then all sensor values are sorted by their numeric value and not by the string value.
The normal sort filter sorts 1,10,100,2,20,200… if the numbers are stored as strings.

But my natsort filter needs a python module “natsort”.
How do I tell homeassistant that the module natsort has to be installed in the dependencies?

You’d need to add it to the manifest file for that custom integration, assuming he built it as an integration. Iirc, he did

Sorry, I added it to helpers/template.py to home assistant core, as you recommended. I updated the original post.

You can’t do it that way. My recommendation for adding it directly to core was to submit a PR to have it properly added to core. If you’re adding external libraries, then you should attempt to use his custom integration. I can’t guarantee that will work, but it will allow you to add an external lib.

My filter is very important for HA because HA stores sensor values in strings and there is no way to sort them in a useful way. For example I have a list of battery states, and the normal sort filter sorts them like 1%, 100%, 2%, 20%, 30%, 5%, 60%
With my filter, they get sorted 1%, 2%, 5%, 20%, 30%, 60%, 100%

You can store values in attributes as-is. If you store them in the state, they will be strings.

Secondly, the sorting is messed up because you’re storing the values with %. There’s no reason to attach the units to the value.

A simple way to handle this is to remove the last character and convert them to numbers. then sort. All doable in 1 line of jinja.

{{ values | map('replace', '%', '') | map('float') | sort }}

I’m not storing values in sensors. HA is doing that. What do see when you try

{{ states.sensor|sort(attribute="state")|map(attribute="state")|list }}

in the developer tools. You get a list that is somehow ordered, but not in way that is useful.

then you can do exactly what I just said…

{{ states.sensor | map(attribute="state") | map('float', None) | reject('none') | sort }}

You missunderstood my example. The real word case is

{{ states.sensor|sort(attribute="state")|list }}

The reason is that normally I want to keep the whole sensor object and not only the state. If I want a list of empty batteries, of course I not only want the battery value but also the name of the device.

Yes, then this goes back to my original comment that you should use the custom integration with a manifest. I feel like we are going in circles here.

@petro been a hectic few months and I’m getting back to this. I have this code in a file in the custom_templates file and I am able to call it in the Dev tools template editor using this:

{% from 'convertieee.jinja' import flt_2_ieee %}
{{ flt_2_ieee(39) }}

which returns back [0x421C,0x0] as i expect

I have a script that is trying the same thing and I get an error:
Error rendering data template: UndefinedError: 'flt_2_ieee' is undefined
Here is the script config:

modbus_brite_2_set_temp:
  alias: Modbus Brite_2 set temp
  sequence:
    - service: modbus.write_register
      data:
        value: >
          {% from 'convertieee.jinja' import flt_2_ieee %}
          "{{ flt_2_ieee(temp) }}"
        hub: modbus_hub
        unit: 2
        address: 00
  mode: parallel
  max: 3

What am I doing wrong?
HA: 8.4

sounds like you didn’t create the macro properly in the system

1 Like

Since it is working in the Template Dev tool, I concluded that the system was configured correctly. is that not a good test?

if it’s working in dev tools, it’ll work in wherever else you put the template.

I stripped everything out and rebuilt from scratch and it is now working as a custom template macro using the code @petro provided above.

Great job. do you @jms3000 happen to share the code please? I am also dealing something like that. Perhaps @blizzrdof77 can add it to his repo of filters