Hi, I have written a couple of automations, the purpose of which is to get a temperature from a sensor in the middle of a room (the sensor.xiaomi_*) and pass it onto a ZWave thermostatic valve as a temperature offset so that the valve knows what the real temperature is.
Most of the time it works, but sometimes is bombs out with TypeErrors comparing strings and floats
Logger: homeassistant.components.automation.correct_trv_kids_temp
Source: helpers/script.py:1156
Integration: Automation (documentation, issues)
First occurred: 16:22:00 (4 occurrences)
Last logged: 17:05:57
Heating: Correct TRV Kids Temp: Error executing script. Error for call_service at pos 1: Error rendering data template: TypeError: unsupported operand type(s) for -: 'str' and 'float'
The template syntax inside YAML is driving me crazy when there are multiline expressions with logic involved, so I am a bit lost with where I am messing up with variable classes. Any hints on how to correct/debug this very much appreciated. Here is the code for the whole thing:
id: auto_trv_kids_correction
alias: "Heating: Correct TRV Kids Temp"
description: Correct TRV Kids Temperature to that given by room Xiaomi thermometer
trigger:
- platform: state
entity_id: sensor.trv_kids_air_temperature
- platform: state
entity_id: sensor.xiaomi_kids_temperature
condition:
- condition: state
entity_id: input_boolean.heating_season
state: "on"
action:
- service: input_number.set_value
target:
entity_id: input_number.kids_temperature_correction
data:
value: >
{## Read room temp from sensor and from TRV. Calculate difference ##}
{% set sensor_temp = float(states('sensor.xiaomi_kids_temperature')) %}
{% set trv_temp = float(states('sensor.trv_kids_air_temperature')) %}
{% set old_correction = float(states('input_number.kids_temperature_correction')) %}
{% set corr = [-5,(sensor_temp - trv_temp + old_correction)]|max %}
{% set corr= [5,corr]|min %}
{{ '%0.1f'|format(corr) }}
- service: zwave_js.set_config_parameter
data:
parameter: "8"
value: >
{## This takes the above temp corr, multiplies by 10 and passes ##}
{## to the config param ##}
{% set corr = 10*float(states('input_number.kids_temperature_correction')) %}
{{'%0.0f'|format(corr)}}
target:
device_id: 90baba58a787d67149e4371cfa26d9cf
mode: restart
When one of your sensors is unavailable, the float() function doesn’t convert it to a zero but leaves it as a string. This line tries subtracting a mix of strings and numbers:
{% set corr = [-5,(sensor_temp - trv_temp + old_correction)]|max %}
Which results in the error message:
TypeError: unsupported operand type(s) for -: ‘str’ and ‘float’
EDIT
What was left unsaid: Change the usage of float from function call to filter.
{% set sensor_temp = states('sensor.xiaomi_kids_temperature') | float %}
{% set trv_temp = states('sensor.trv_kids_air_temperature') | float %}
{% set old_correction = states('input_number.kids_temperature_correction') | float %}
It may be that sometimes either states('sensor.xiaomi_kids_temperature') or states('sensor.trv_kids_air_temperature') returns something other than a numeric value (e.g., ‘unknown’ or ‘unavailable’). In that case, the float function will return the string. I.e.,
{{ float('unavailable') }}
will return 'unavailable', which is a string. And you can’t use the subtraction operator with one operand being a string and the other being a number.
Generally it’s better to use the float filter instead of the float function. The float filter will return a default value if its argument is not a numeric value. The default default is zero, but you can specify a different default. E.g., you could use one of these:
|float
|float(100)
as in:
{% set sensor_temp = states('sensor.xiaomi_kids_temperature')|float %}
{% set trv_temp = states('sensor.trv_kids_air_temperature')|float %}
But, really, if either of these are not a numeric value, it’s probably better not to do anything. So maybe:
id: auto_trv_kids_correction
alias: "Heating: Correct TRV Kids Temp"
description: Correct TRV Kids Temperature to that given by room Xiaomi thermometer
trigger:
- platform: state
entity_id:
- sensor.trv_kids_air_temperature
- sensor.xiaomi_kids_temperature
variables:
sensor_temp: "{{ float(states('sensor.xiaomi_kids_temperature')) }}"
trv_temp: "{{ float(states('sensor.trv_kids_air_temperature')) }}"
condition:
- condition: state
entity_id: input_boolean.heating_season
state: "on"
- condition: template
value_template: "{{ sensor_temp is number and trv_temp is number }}"
action:
- service: input_number.set_value
target:
entity_id: input_number.kids_temperature_correction
data:
value: >
{## Read room temp from sensor and from TRV. Calculate difference ##}
{% set old_correction = states('input_number.kids_temperature_correction')|float %}
{% set corr = [-5,(sensor_temp - trv_temp + old_correction)]|max %}
{% set corr= [5,corr]|min %}
{{ '%0.1f'|format(corr) }}
- service: zwave_js.set_config_parameter
data:
parameter: "8"
value: >
{## This takes the above temp corr, multiplies by 10 and passes ##}
{## to the config param ##}
{% set corr = 10*float(states('input_number.kids_temperature_correction')) %}
{{'%0.0f'|format(corr)}}
target:
device_id: 90baba58a787d67149e4371cfa26d9cf
mode: restart