Be mindful of operator and filter precedence in template expressions

Just something stupid I found the hard way, maybe save someone else some troubles…

I have a multi-sensor sort of device, built into an ESP8266-based “night light” that transmits among other things, a barometric pressure measurement. So I create an MQTT sensor, and do some math to convert from millimeters of mercury units to inches of mercury because here in the USA, we resist change and the metric system.

  - name: nightlight1 pressure
    platform: mqtt
    unit_of_measurement: "inHg"
    device_class: pressure
    state_topic: 19916/tele/NightLight1/SENSOR
    # convert mm of mercury to inches of mercury
    value_template: '{{ (value_json["BME280"]["Pressure"] | float) / 25.4 | round(2) }}'
    payload_available:  "Online"
    payload_not_available: "Offline"

The result was still a sensor value with way too many digits of precision, rather than the two that I had intended. Perhaps I got used to seeing and treating the | system like a UNIX pipe, but it’s not quite like that…

But if I change the template to add in some parens:

    value_template: '{{ ((value_json["BME280"]["Pressure"] | float) / 25.4) | round(2) }}'`

this works. Apparently the rounding operator was applying to the 25.4 constant rather than the entire expression. Which makes sense… had I thought about it ahead of time. duh.

Apparently, I’m not the first to run afoul of this ambiguity in operator precedence rules in the jinja2 template engine. See https://github.com/pallets/jinja/issues/379 and https://stackoverflow.com/questions/23248850/order-of-operations-for-jinja2-filters

1 Like