Sensor output not rounding round (1)

Any idea why 1 sensor particularly is not rounding?

    sensors:
      cyan_toner_level:
        friendly_name: 'Cyan Toner Level'
        unit_of_measurement: '%'
        value_template: '{{ ((states.sensor.prncyanlvl.state | float) / (states.sensor.prncyancap.state | float)) * 100 | round(1) }}'
      magenta_toner_level:
        friendly_name: 'Magenta Toner Level'
        unit_of_measurement: '%'
        value_template: '{{ ((states.sensor.prnmagentalvl.state | float) / (states.sensor.prnmagentacap.state | float)) * 100 | round(1) }}'
      yellow_toner_level:
        friendly_name: 'Yellow Toner Level'
        unit_of_measurement: '%'
        value_template: '{{ ((states.sensor.prnyellowlvl.state | float) / (states.sensor.prnyellowcap.state | float)) * 100 | round(1) }}'
      black_toner_level:
        friendly_name: 'Black Toner Level'
        unit_of_measurement: '%'
        value_template: '{{ ((states.sensor.prnblacklvl.state | float) / (states.sensor.prnblackcap.state | float)) * 100 | round(1) }}'

image

Here you are rounding the number 100.

Likewise for the others. Add some parentheses to adjust the order of operations, and please use this form of state template to avoid errors if the entity is not initialised (like during start up):

value_template: "{{ ( states('sensor.prncyanlvl')|float / (states('sensor.prncyancap')|float * 100) )|round(1) }}"

Edit: also note that due to epsilon errors (essentially floating point math precision) sometimes even the round function does not work and you should format the output instead:

value_template: "{{ '{:.1%}'.format( states('sensor.prncyanlvl')|float / (states('sensor.prncyancap')|float * 100) ) }}"
3 Likes

Hi, @tom_l thank you for taking the time to respond.

I have tried what you sugested but I get:

    sensors:
      cyan_toner_level:
        friendly_name: 'Cyan Toner Level'
        unit_of_measurement: '%'
        #value_template: '{{ ((states.sensor.prncyanlvl.state | float) / (states.sensor.prncyancap.state | float)) * 100 | round(1) }}'
        value_template: "{{ ( states('sensor.prncyanlvl')|float / (states('sensor.prncyancap')|float * 100) )|round(1) }}"
      magenta_toner_level:
        friendly_name: 'Magenta Toner Level'
        unit_of_measurement: '%'
        #value_template: '{{ ((states.sensor.prnmagentalvl.state | float) / (states.sensor.prnmagentacap.state | float)) * 100 | round(1) }}'
        value_template: "{{ ( states('sensor.prnmagentalvl')|float / (states('sensor.prnmagentacap')|float * 100) )|round(1) }}"
      yellow_toner_level:
        friendly_name: 'Yellow Toner Level'
        unit_of_measurement: '%'
        value_template: '{{ ((states.sensor.prnyellowlvl.state | float) / (states.sensor.prnyellowcap.state | float)) * 100 | round(1) }}'
      black_toner_level:
        friendly_name: 'Black Toner Level'
        unit_of_measurement: '%'
        value_template: '{{ ((states.sensor.prnblacklvl.state | float) / (states.sensor.prnblackcap.state | float)) * 100 | round(1) }}'

image

Ok, so this works:
value_template: '{{ (((states.sensor.prnmagentalvl.state | float) / (states.sensor.prnmagentacap.state | float)) * 100) | round(1) }}'

This gave the 7.0000000000001%:
value_template: '{{ ((states.sensor.prnmagentalvl.state | float) / (states.sensor.prnmagentacap.state | float)) * 100 | round(1) }}'

This gave 0.0%:
value_template: "{{ ( states('sensor.prnmagentalvl')|float / (states('sensor.prnmagentacap')|float * 100) )|round(1) }}"

This gave 0.0%
value_template: "{{ '{:.1%}'.format( states('sensor.prnmagentalvl')|float / (states('sensor.prnmagentacap')|float * 100) ) }}"

I would really like to understand why…?

It’s still an order of operations issue - if you remember BODMAS or BIDMAS from school that’s basically the answer! I’ll explain how each calulation is resolved:

For the sake of argument, I’m going to say that prnmagentalvl is 14.5 and prnmagentacap is 200.

Remember that before you can round something, you have to know what it is. So if it is in brackets you have to calculate the operation inside the brackets before rounding the result. If the number to be rounded isn’t in brackets then you can just round it straight away.

Also remember that for everything before the pipe, you start with the deepest nested brackets and then work your way out.

First example:
(((14.5) / (200)) * 100) | round(1)
Ditch extraneous brackets:
((14.5 / 200) * 100) | round(1)
Divide 14.5 by 200:
(0.0725 * 100) | round(1)
Multiply 0.0725 by 100:
7.25 | round(1)
Round 7.25:
7.3

Second example:
((14.5) / (200)) * 100 | round(1)
Ditch extraneous brackets:
(14.5 / 200) * 100 | round(1)
Round the 100:
(14.5 / 200) * 100.0
Divide 14.5 by 200:
0.0725 * 100
Multiply 0.0725 by 100:
7.25

Third example:
(14.5 / (200*100)) | round(1)
Multiply 200 by 100:
(14.5 / 20000) | round(1)
Divide 14.5 by 20000:
0.000725 | round(1)
Round 0.000725:
0.0

I’m not familiar with the {:.%} format in the third example, but the bit after .format evaluates like this:
(14.5/(200*100))
Multiply 200 by 100:
(14.5 / 20000)
Divide 14.5 by 20000:
0.000725

@EKC, @tom_l, thank you both. I have at least sorted out the issue.
I understand you both, my problem had to do with the order of operation indeed.

Although I did not know BODMAS, had to look it up in google. But yes I now know what it is… We call it differnt in our country :-).

Thanks again!

I’d still like to know why you got this result:

This gave the 7.0000000000001%:
value_template: '{{ ((states.sensor.prnmagentalvl.state | float) / (states.sensor.prnmagentacap.state | float)) * 100 | round(1) }}'

This gave 0.0%:
value_template: "{{ ( states('sensor.prnmagentalvl')|float / (states('sensor.prnmagentacap')|float * 100) )|round(1) }}"

The templates should be equivalent except for rounding and that the second one won’t generate errors when the sensor is not available and should always be used. See the warning here: https://www.home-assistant.io/docs/configuration/templating/#states

It’s because of the brackets around (states(‘sensor.prnmagentacap’)|float * 100). The first example divides the level by the cap and then multiplies the quotient by 100 (correct), while the second example multiplies the cap by 100 and then divides the level by the product (incorrect).

This should work:

value_template: "{{ ( (states('sensor.prnmagentalvl')|float / states('sensor.prnmagentacap')|float) * 100)|round(1) }}"
1 Like