Help with scripting

Hi, I’m getting very confused googling for HA scripting, then jinja, then YAML, then Templates, then back round again, then considering nodered and pyscript and appdaemon, then back round to scripting again… If there’s a good source that centralises using YAML, templating, jinja from a HA PoV I’d appreciate a link. As it stands I keep on seeing comments which end up like ‘Oh, you can’t use {{ }} in that setting, or Developer Templating doesn’t work that way in scripts’ or something else which means I’m just guessing what to try next.

My issue is I want a templating script like this:

{% set pct = (((faketemp /30 ) *100 ) | round(0) )  %} 
{{ faketemp }}C = {{ pct }}%
{% if pct < 51 -%}
  {% set bp = (((50 - pct)*2 ) | round(0) | int )  %} 
  {% set rp = 0  %} 
{%- else -%}
  {% set rp = ((( pct - 50)*2 ) | round(0) | int )  %} 
  {% set bp = 0  %} 
{%- endif %}
{% set gp = (((100-(bp+rp))/4 )| round(0) | int )  %} 
{% set MqttCmd = "Backlog led1 " ~ rp +"," ~ gp +"," ~ bp %}
{{ MqttCmd }} 

to work in an HA script called by an automation. I have tried so many different ways of tweaking the script but keep on hitting silly errors like the ‘str/int’ problem - but with no clue where that problem is.

The idea of the script is that a temperature is converted to a percentage, and that is converted into RGB and sent to Tasmota to light up an led. I already have a working version that converts the temperature directly but I want a more generic program that converts a % so I can use similar code for other sensors.

The script I have (currently) is:

sequence:
  - variables:
      jinja_script: >
        {% set Pct = ((((states('sensor.temp_e_temperature') /30 ) | int) *100 ) | round(0) | int ) %}
        {% if ( Pct < 51) -%}
          {% set LedR = 0 | int %} 
          {% set LedB = ( ( (50 - pct)*2 ) | round(0) | int ) %} 
        {%- else  -%}
          {% set LedB = 0 | int %} 
          {% set LedR = ( ( (pct - 50)*2 ) | round(0) | int ) %} 
        {%- endif %} 
        {% set LedG = (((100-(LedB+LedR))/4 )| round(0) | int )  %}
        {% set MqttCmd = "Backlog led1 " ~ LedR + "," ~ LedG + "," ~ LedB %}
  - service: notify.viaemail
    data:
      title: "Temp is: {{ states(\"sensor.temp_e_temperature\") }}"
      message: "{{ MqttCmd }}"
      target: ha@emailaddress

And the run error is
Error: TypeError: unsupported operand type(s) for /: ‘str’ and ‘int’

I think I’ve added ‘int’ everywhere I can :slight_smile:

I’m keen to get to grips with this rather than add another integration but I have struggled with so many syntax problems and a lack of step-through debug that I really need some help.

That error is due to this line:

{% set Pct = ((((states('sensor.temp_e_temperature') /30 ) | int) *100 ) | round(0) | int ) %}

The state value of any entity is handled as a string, even if the value appears to be numeric. Therefore dividing a string value by 30 is what caused the error message. You have to convert it using either float() or int(). You should also provide a default value in case the string value can’t be converted. In the following example, float(0) means the default value is zero.

Here’s the corrected version:

sequence:
  - variables:
      MqttCmd: >
        {% set Pct = (states('sensor.temp_e_temperature') | float(0) / 30 * 100 ) | round(0) %}
        {% if Pct < 51 -%}
          {% set LedR = 0 %} 
          {% set LedB = ((50 - Pct)*2 ) | round(0) %} 
        {%- else  -%}
          {% set LedB = 0 %} 
          {% set LedR = ((Pct - 50)*2 ) | round(0) %} 
        {%- endif %} 
        {% set LedG = ((100 - LedB + LedR) / 4) | round(0) %}
        Backlog led1 {{ LedR }},{{ LedG }},{{ LedB }}}
  - service: notify.viaemail
    data:
      title: "Temp is: {{ states('sensor.temp_e_temperature') }}"
      message: "{{ MqttCmd }}"
      target: ha@emailaddress
1 Like

Thanks for the float correction, that makes sense and I can kick myself for ignoring that part in the developer template…

The way you made the jinja block spit out a variable is not something that has occurred to me. Can I put a jinja block anywhere in a script on the understanding that whatever it sends to stdout is what the script sees? If so, should I assume that whatever occurs in the jinja block is otherwise unavailable to the script or another jinja block (for example, is the LedG variable accessible further down the script?

In the example I posted, MqttCmd is a script variable. Its value is accessible throughout the automation’s action section. In contrast, Pct, LedR, LedG, and LedB are Jinja2 variables. They’re undefined outside of the MqttCmd section.

Reference: Scripts - Variables

Thanks…

Your link to ‘scripts - variables’ is what I find so frustrating though - I understand script variables but trying to figure out jinja variables or code blocks to create script variables from that link has proven tough.

You’ve given me a big pointer and it may all fall into place on my next script…