How to make multiline&formatted calculations inside a script?

Hi!
I have a template sensor, which is calculating a difference between setpoints and real values. Its working, how i want it. My problem is, i would like to implement this calculation inside a script, but i cant figure it out.
I tried to read docs here and on jinja site. But i didnt find anything helpful.
Is it possible to make something like this inside a script:

data_template:
  entity_id: climate.c69f59b0
  temperature: >
      {% set mean_temp = states('sensor.beallitott_homerseklet') | float %}
      {% set real_temp = states('sensor.legminoseg_homerseklet') | float %}
      {% set set_temp = state_attr('climate.c69f59b0' , 'temperature') | float %}
      {% set meas_temp = state_attr('climate.c69f59b0' , 'current_temperature') | float %}
      {% set diff = real_temp - mean_temp + set_temp - meas_temp %}
      " {{ diff | float | round(0) }} "
service: climate.set_temperature

The result of this script is the folowing: “expected float for dictionary value @ data[‘temperature’]. Got None”

Thanks in advance!
Zsolt

I think the quotes should not be there.

3 Likes

Without them the response is unknown error :slight_smile:

Possibly it’s that you put the “round(0)” in the output which effectively turns it into an integer instead of a float?

Or I don’t know if it makes any difference or not but try changing “data_template” to just “data”. “data_template” was deprecated a long time ago. But I think it should still be OK tho.

Otherwise, maybe the climate.set_temperature service doesn’t support templating in the temperature field?

It doesn’t look like there’s anything wrong in the template that I can see. Especially if the same template works and shows the correct result in a template sensor. But the sensor won’t care about a float or int result either.

I also don’t know why you get a different error without the quotes as mentioned above. It shouldn’t need them as far as I know.

1 Like

Copy-paste the following template into the Template Editor and report the results.

{% set mean_temp = states('sensor.beallitott_homerseklet') | float(0) %}
MEAN: {{ mean_temp }}
{% set real_temp = states('sensor.legminoseg_homerseklet') | float(0) %}
REAL: {{ real_temp }}
{% set set_temp = state_attr('climate.c69f59b0', 'temperature')  %}
SET: {{ set_temp }}
{% set meas_temp = state_attr('climate.c69f59b0', 'current_temperature') %}
MEAS: {{ meas_temp }}
{% set diff = real_temp - mean_temp + set_temp - meas_temp %}
DIFF: {{ diff }}
{{ diff | round(0) }}
2 Likes

This is the result:

MEAN: 21.0

REAL: 20.1

SET: 20

MEAS: 20

DIFF: -0.8999999999999986
-1

Your template performs a calculation that produces a negative value.

Then it attempts to use that negative value to set the temperature of climate.c69f59b0. You can’t set a climate entity to a negative value.

I don’t know what is the goal of that calculation but you need to re-design it to ensure it doesn’t produce negative values.

Sh*t. :smiley:
I copied the bad calculation into the template. I need to decrease the setpoint with result from this. And i tried to pass the bad value to the AC…
Thanks for the idea, how can i test my scripts!

This is the final format which is accepted by the AC unit:

data:
  entity_id: climate.c69f59b0
  temperature: 
      {% set mean_temp = states('sensor.beallitott_homerseklet') | float %}
      {% set real_temp = states('sensor.legminoseg_homerseklet') | float %}
      {% set set_temp = state_attr('climate.c69f59b0' , 'temperature') | float %}
      {% set meas_temp = state_attr('climate.c69f59b0' , 'current_temperature') | float %}
      {% set diff = real_temp - mean_temp + set_temp - meas_temp %}
      {% set new_setpoint = set_temp - diff %}
      "{{ new_setpoint | float | round(0) }}"
service: climate.set_temperature
  • An entity’s state value is always a string, even when it’s numeric. Therefore the float filter, or int filter, is needed to convert it to a number. However, you should supply the filter with a default value. Because if the value supplied to float is non-numeric, it will produce an error message. If a non-numeric value is supplied to float(0) it will use 0 as the default (you can set the default to whatever you want).

  • An entity’s attribute can contain a value that is a number, list, dictionary, string, etc. In this case, the temperature and current_temperature are numbers so there’s no need to use the float filter.

  • If you add a line continuation character after an entity’s option, it means the template starts on the next line and may span multiple lines. In that case, you should not wrap the template in any quotes. Here are examples of line continuation characters:
    >
    >-
    |

Reference: https://yaml-multiline.info/

  • The variable named new_setpoint contains a number so there’s no need to use the float filter before applying the round filter.

  • The modern way of identifying a service call’s entity is by using the target option. All else is under the data option. The data_template option was deprecated a long time ago and now data also accepts templates.

Example

service: climate.set_temperature
target:
  entity_id: climate.c69f59b0
data:
  temperature: >
      {% set mean_temp = states('sensor.beallitott_homerseklet') | float(0) %}
      {% set real_temp = states('sensor.legminoseg_homerseklet') | float(0) %}
      {% set set_temp = state_attr('climate.c69f59b0', 'temperature') %}
      {% set meas_temp = state_attr('climate.c69f59b0', 'current_temperature') %}
      {% set diff = real_temp - mean_temp + set_temp - meas_temp %}
      {% set new_setpoint = set_temp - diff %}
      {{ new_setpoint | round(0) }}
2 Likes

Thank you very much!
Now it looks a lot better! :slight_smile: