Updating Templates with the new default values in 2021.10.x

side question: running the daily now contains those |int changes? what was the cli command again to run the daily’s? foreseeing a longer period of editing, Id like to have a go asap…

1 Like

well thats a huge change on |int :wink:

1 question to be sure on the map(int):

{% set alert_level = states('input_number.battery_alert_level')|int(default=0) %} {{expand('group.battery_sensors')
         |map(attribute='state')
         |rejectattr('state','in',['unknown','unavailable'])
         |map('int')
         |select('<',alert_level)
         |list|count}}

should be:

{% set alert_level = states('input_number.battery_alert_level')|int(default=0) %} {{expand('group.battery_sensors')
         |map(attribute='state')
         |rejectattr('state','in',['unknown','unavailable'])
         |map('int',default=0)
         |select('<',alert_level)
         |list|count}}

?
couldnt find the direct explanation on int in that form

this is really cool:

        availability: >
          {% set items = expand('group.doors') %}
          {% set x = ['unavailable','unknown'] %}
          {{expand(items)|rejectattr('state','in',x)|list|count == items|count}}

adding it to all binary template sensors, just for the fun of it :wink:

The int filter takes only one argument, namely the default value, Home Assistant’s current implementation of the int filter takes two arguments and the first one is the default value (the second one is the base), so there’s no obligation to supply “default=” when specifying the default value. map('int', 0) is sufficient.

thanks, retesting as I write. guess I peaked too much at Petro’s changes https://github.com/Petro31/home-assistant-config/commit/5bde1c33b1fb2f52a3a91bc1c4a018c6c0a82288 and didnt think about the differences…

this error was huge, and took many hundreds of lines. somehow it must have been tested continously during startup.

nope still renders:

Template warning: 'int' got invalid input 'unknown' when rendering template '{% set alert_level = states('input_number.battery_alert_level')|int(default=0) %} {{expand('group.battery_sensors')
         |map(attribute='state')
         |rejectattr('state','in',['unknown','unavailable'])
         |map('int',0)
         |select('<',alert_level)
         |list|count}}' but no default was specified. Currently 'int' will return '0', however this template will fail to render in Home Assistant core 2022.1

If you wish, you can reduce it to this:

        availability: >
          {% set items = expand('group.doors') %}
          {{ items|rejectattr('state','in',['unavailable','unknown'])|list == items }}

FWIW, even though it’s shorter (because it doesn’t use the count filter) it might involve a few more CPU cycles because it’s comparing one list to another whereas petro’s original version compares one integer to another. If that concerns you, you can revert to comparing integers:

        availability: >
          {% set items = expand('group.doors') %}
          {{ items|rejectattr('state','in',['unavailable','unknown'])|list|count == items|count }}
1 Like

Doh! :man_facepalming:

Serves me right for not checking the documentation.

According to the Jinja2 docs, default is second and base is last:

jinja-filters.int(value: Any, default: int = 0, base: int = 10 ) → int

Convert the value into an integer. If the conversion doesn’t work it will return 0. You can override this default using the first parameter. You can also override the default base (10) in the second parameter, which handles input with prefixes such as 0b, 0o and 0x for bases 2, 8 and 16 respectively. The base is ignored for decimal numbers and non-string values.

Uh oh, maybe I made a mistake

Yep, gonna pull back that PR…

It can be confusing because the Jinja2 docs describe its filters like when they are used as functions, so in that case int can take three arguments. However, Home Assistant’s current implementation of int is only as a filter, not a function. As a filter, it can take two arguments where the first is the default value and the last is the base.

I was basing it off pythons int

Ehh, just for me then… where does this leave my template? Why the error? And more importantly, how to fix ?

the 2 Int’s what do I set them to?

{%- set alert_level = states('input_number.battery_alert_level')|int(default=0) %} {%- set count = expand('group.battery_sensors')
                       |map(attribute='state')
                       |rejectattr('state','in',['unknown','unavailable'])
                       |map('int',0)
                       |select('<',alert_level)
                       |list|count %}
{% set phrase = 'battery is' if count == 1 else 'batteries are' %} {%- if count > 0 %} {%- for s in expand('group.battery_sensors')
              if s.state not in ['unknown','unavailable','None'] and
                 s.state|int(default=0) < alert_level %}
{%- if loop.first %}{{loop.length}} {{phrase}} below {{alert_level}} %: {% endif %} {{s.name + ': ('+ s.state + '%),\n'}} {%- endfor %} {%- else %} All batteries above {{alert_level}} % {%- endif %}

Odd thing is, when I have a running system, I can’t force a warning on this template…So might it be some startup issue? Maybe I should add an availability template?

think this does it:

      - unique_id: low_level_batteries
        name: Low level batteries
        state: >
          {% set alert_level = states('input_number.battery_alert_level')|int(default=0) %}
          {{expand('group.battery_sensors')
                   |map(attribute='state')
                   |rejectattr('state','in',['unknown','unavailable'])
                   |map('int',default=0)
                   |select('<',alert_level)
                   |list|count}}
        icon: mdi:battery-alert
        attributes:
          list_low: >
            {%- set alert_level = states('input_number.battery_alert_level')|int(default=0) %}
            {%- set count = expand('group.battery_sensors')
                                   |map(attribute='state')
                                   |rejectattr('state','in',['unknown','unavailable'])
                                   |map('int',default=0)
                                   |select('<',alert_level)
                                   |list|count %}
            {% set phrase = 'battery is' if count == 1 else 'batteries are' %}
            {%- if count > 0 %}
            {%- for s in expand('group.battery_sensors')
                          if s.state not in ['unknown','unavailable','None'] and
                             s.state|int(default=0) < alert_level %}
            {%- if loop.first %}{{loop.length}} {{phrase}} below {{alert_level}} %: {% endif %}
            {{s.name + ': ('+ s.state + '%),\n'}}
            {%- endfor %}
            {%- else %} All batteries above {{alert_level}} %
            {%- endif %}
          list_all: >
            {%- for s in expand('group.battery_sensors')%}
            {{s.name + ': ('+ s.state + '%),\n'}}
            {%- endfor %}

pff

For a such a conceptually simple change this new templating update seems to be causing a lot of work and questions.

Can I ask a couple of simple(?) ones…

In general, when there is no way to provide a sensible default (i.e. it would produce a result that is no better than a guess) does it make sense to always provide default=none? There seems to be no way to guard against an invalid incoming date like you can for numbers (is_number).

The current example I am working on is strptime, There is no ‘sensible valid’ default for sensor.next_trains_estimated.


{% set estimated = strptime(states('sensor.next_trains_estimated'), "%H:%M") %}
{% set tnow = strptime(now().strftime('%H:%M'),  "%H:%M") %}
{% set time_to_next_train = (estimated - tnow).total_seconds() / 60 %}
{% set time_to_next_train = time_to_next_train | round %}

And, am I reading this all correctly, the next version of HA introduces more of these e.g int? Why weren’t they all included at once?


And finally a minor rhetorical rant. I know all the stock answers but I do think this apparently-simple-but-actually-quite-seismic change could have been better documented. The OP here is obviously very instructive but surely this information should be in the docs at release time and not have to be buried in the forum where only a few will see it.

I do think HA let’s itself down on two issues. Communication (see the latest Tuya issue) and documentation. It is far better than it was but still not really good enough when things get added (I believe the main source of info to get the energy integration working is still the Blog post or the ‘Developer docs’) or ‘broken’ by upgrades (e.g. these templates).

2 Likes

Just wait til 2021.11 for that one. A new filter and function today_at will make that template easier.

simply wondering why a template like:

      - unique_id: ram_too_high
        name: Ram usage too high
        state: >
          {{states('sensor.memory_use_percent')|int > 85}}

doesnt issue a warning on the |int without a default

might be wide of the mark here (and probably well out of my depth so be gentle :slight_smile: ), but isn’t it a case the the Warning message currently only appears when a Template presents an invalid result…
So taking your template then the Memory Usage will pretty much always have an Integer Value (once HA is running on your device) so it’ll never throw an invalid result, etc therefore doesn’t warn in your logs.
(and following on from that it’ll only error if that sensor ever goes unavailable which I guess is unlikely)
“Technically” you should supply a default but operationally there is no need as the sensor is always(nearly always) providing a valid result

That’s my understanding of these new changes anyway…may be wrong so be grateful for confirmation/correction…

2 Likes

Because your sensor must never go Unavailable or unknown

1 Like

Hello,

How can I fix this?
Now give me a warning…

automation:

    - alias: Rádio - Play
      trigger:
        - platform: state
          entity_id: input_boolean.radio_hall,  input_boolean.radio_cozinha,  input_boolean.radio_quarto
          to: 'on'
      action:
        - service: media_player.volume_set
          data_template:
            entity_id: >
              {% if trigger.from_state.entity_id == "input_boolean.radio_hall" %} media_player.a7_fully
              {% elif trigger.from_state.entity_id == "input_boolean.radio_cozinha" %} media_player.sala_de_estar
              {% elif trigger.from_state.entity_id == "input_boolean.radio_quarto" %} media_player.quarto_wall
              {% endif %}
            volume_level: >
              {% if '09:00' <= states.sensor.time.state < '10:00' | timestamp_custom('%H:%M') %}
                0.35
              {% elif '10:00' <= states.sensor.time.state < '22:00' | timestamp_custom('%H:%M') %}
                0.40
              {% elif '22:00' <= states.sensor.time.state <= '23:59' | timestamp_custom('%H:%M') %}
                0.30
              {% else %}
                0.25
              {% endif %} 

Error:

Logger: homeassistant.helpers.template
Source: helpers/template.py:1210
First occurred: 09:39:03 (3 occurrences)
Last logged: 09:39:03

Template warning: 'timestamp_custom' got invalid input '10:00' when compiling template '{% if '09:00' <= states.sensor.time.state < '10:00' | timestamp_custom('%H:%M') %} 0.35 {% elif '10:00' <= states.sensor.time.state < '22:00' | timestamp_custom('%H:%M') %} 0.40 {% elif '22:00' <= states.sensor.time.state <= '23:59' | timestamp_custom('%H:%M') %} 0.30 {% else %} 0.25 {% endif %}' but no default was specified. Currently 'timestamp_custom' will return '10:00', however this template will fail to render in Home Assistant core 2021.12
Template warning: 'timestamp_custom' got invalid input '22:00' when compiling template '{% if '09:00' <= states.sensor.time.state < '10:00' | timestamp_custom('%H:%M') %} 0.35 {% elif '10:00' <= states.sensor.time.state < '22:00' | timestamp_custom('%H:%M') %} 0.40 {% elif '22:00' <= states.sensor.time.state <= '23:59' | timestamp_custom('%H:%M') %} 0.30 {% else %} 0.25 {% endif %}' but no default was specified. Currently 'timestamp_custom' will return '22:00', however this template will fail to render in Home Assistant core 2021.12
Template warning: 'timestamp_custom' got invalid input '23:59' when compiling template '{% if '09:00' <= states.sensor.time.state < '10:00' | timestamp_custom('%H:%M') %} 0.35 {% elif '10:00' <= states.sensor.time.state < '22:00' | timestamp_custom('%H:%M') %} 0.40 {% elif '22:00' <= states.sensor.time.state <= '23:59' | timestamp_custom('%H:%M') %} 0.30 {% else %} 0.25 {% endif %}' but no default was specified. Currently 'timestamp_custom' will return '23:59', however this template will fail to render in Home Assistant core 2021.12