Updating Templates with the new default values in 2021.10.x

so back to this original template you posted, you should use

{{ states('sensor.boiler_amps')|float(0) > 1 }}

because it will end up with 0 > 1 as false and won’t trigger.

Then use an availability template to monitor the original sensor.

template:
  - binary_sensor:
      - name: "Has Unavailable States"
        state: "{{ states.sensor | selectattr('state', 'in', ['unavailable', 'unknown', 'none']) | list | count }}"

I have to change quite few things but it will in the end simplify my notifications :+1:

1 Like

To my shame I have rarely used availability (templates) so bear with me here…

Am I right in thinking that the following template is ‘good’ i.e. it will either work without errors warnings or show as unavailable?

Is the float(default='none') and the round(2, default='none') for the sensor a good choice because the availability template will stop this even being evaluated if the sensor is 'unknown' or 'unavailable'?

If the sensor is populated with anything other than a valid numeric there is a deeper problem that I need to know about.

As an observation, the float default seems to be unfortunate overkill (but obviously now required) for the input_number entities as they can’t ever be anything other than number?

state: >
  {% set unit_price = states('input_number.octopus_gas_unit_price') | float(default='none') %}
  {% set standing_charge = states('input_number.octopus_gas_standing_charge') | float(default='none') %}
  {% set calorific_value = states('input_number.octopus_gas_calorific_value') | float(default='none') %}
  {% set cost = states('sensor.octopus_gas_consumption_kwh_yesterday') | float(default='none') * unit_price / 100 + standing_charge / 100 | round(2, default='none') %}
  {{ '{:02.2f}'.format(cost) | string }}
availability: >
  {{ states('sensor.octopus_gas_consumption_kwh_yesterday') not in ['unknown','unavailable'] }}

1 Like

you want to make sure the are all available

I use this for my availability templates that require everything to be available:

{% set items = 'sensor.memory_free', 'sensor.memory_use' %}
{{ expand(items) | rejectattr('state','in',['unknown','unavailable']) | list | count == items | count }}

Then just add whatever you want to items.

1 Like

i forgot to mention, then just use 0 as the default, the calc will be thrown out anyways

thats nice indeed. was thrown off at first by the order in | list | count == items | count but then realized it is actually doing
{{ ((expand(items) | rejectattr('state','in',['unknown','unavailable'])) | list | count) == (items | count) }}

we can use this even in a 1 entity list but then need the on the items:

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

having had these for ages:

  - binary_sensor:

      - unique_id: ink_level_black_threshold
        name: Ink level black threshold
        state: >
          {{states('sensor.epson_ink_level_black') is not none and
            states('sensor.epson_ink_level_black')|int <
            states('input_number.ink_level')|int}}

considering the above availability (which I supposedly checked with the is not none and the upcoming defaults for |int, should I change these to

      - unique_id: ink_level_black_threshold
        name: Ink level black threshold
        state: >
          {{states('sensor.epson_ink_level_black')|int(default=0) <
            states('input_number.ink_level')|int}}
        availability: >
          {% set items = ['sensor.epson_ink_level_black'] %}
          {{expand(items)|rejectattr('state','in',['unknown','unavailable'])
            |list|count == items|count}}

?
(where no default would be required on the input_number I guess?)


        availability: >
          {{states('sensor.epson_ink_level_black') not in ['unknown','unavailable']}}

might be simpler :wink:

1 Like

Yes if the calculation only involves 1 other entity, no reason to use generators.

FYI, I made an edit to the original post that explains arguments better. Take a look.

yes, I did and thanks!

What might be an addition to that, is deciding whether one wants a template to return a value, and thus report an entity with a state, at all times, or, whether one wants a template to show unavailable when no valid input was received.

For your post eg this

{{ 1.43 | round(default=0) }} returning 0 or
{{ 1.43 | round(default=none) }} returning unavailable

currently, I find that choice to be the biggest challenge throughout the config. Especially so, when combined calculations are used, either inside the 1 template, or from 1 template entity to another

same goes for the |int(default=0) in the next update. Seems logical to add that when the input is from an uncertain source, like another integration. But when used as a direct number like an input_number, which always has a value, why would a default be needed at all…
what about the input_numbers in the templates I use above, do I need a |int(default=50) on those?

{{states('sensor.epson_ink_level_black')|int(default=0) <
            states('input_number.ink_level')|int(default=50)}}

hope the warnings in the next updates logger will tell.

1 Like

If it doesn’t produce a warning, no need to update it

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.