Newbie question about templates and automations

New user here, so apologies in advance. My goal is to change the color of a Sengled RGBW light based on PurpleAir’s pm2.5 measurement. I’m oh so close. Basically, what I want to do is map the pm2.5 values to an appropriate HS_color value…

I believe my problem is that templates aren’t evaluated when I think they are, and I’m guilty of a classic “binding problem.”

What I’ve come up with so far (clever in so far as it goes as it maps pm2.5 values from green through yellow to red for 0…150, and purple for anything higher)

entity_id: light.sengled_e11_n1ea_50e10800_level_light_color_on_off
hs_color:
  {% set pm25=states("sensor.purpleair_pm25") | int -%}
  {%- if pm25 <= 50 -%}
    {%- set h=120-4*pm25 -%}
  {%- elif pm25 <= 150 -%}
   {%- set h=[60-0.6*(pm25-50)]|max -%}
  {%- else -%}
    {%- set h=500 -%}
  {%- endif -%} 
  {{ h | int }}
  100

When I run this in the template tab of developer tools I get the right thing:

entity_id: light.sengled_e11_n1ea_50e10800_level_light_color_on_off
hs_color:
  72
  100

Of course this works perfectly when I type the above four lines into the Services section of Developer Tools, but typing in the version with the templates doesn’t get past the syntax checker:

image

Yeah, that service tab does not take templates.

Also, your h variable won’t last beyond the {% if %} / {% endif%}. Once that scope is done, h is no longer valid. It works in the template editor because the entire thing is one giant scope. It can really throw you off.

Inside of sequences, you can get around this with the variables action.

- variables:
    h_value: > 
      {{% set pm25=states("sensor.purpleair_pm25") | int -%}
      {%- if pm25 <= 50 -%}
        {{ 120 - 4*(pm25 | int) }}
      {%- elif pm25 <= 150 -%}
        {{ [60-0.6*(pm25-50)] | max }}
      {%- else -%}
        500
      {%- endif -%}
- service: light.turn_on
  data:
    entity_id: light.sengled_e11_n1ea_50e10800_level_light_color_on_off
    color: "{{ h_value }}"

For a template light (which is seems you have), you’ll have to use a namespace. This will allow the variable to live beyond the scope of the template node.

hs_color:
  {% set pm25=states("sensor.purpleair_pm25") | int -%}
  {% set ns = namespace() %}
  {%- if pm25 <= 50 -%}
    {%- set ns.h=120-4*pm25 -%}
  {%- elif pm25 <= 150 -%}
   {%- set ns.h=[60-0.6*(pm25-50)]|max -%}
  {%- else -%}
    {%- set ns.h=500 -%}
  {%- endif -%} 
  [{{ ns.h | int }}, 100]

And finally, this will only work in 0.118 (or 0.117 if you turn on beta templates in the config). Before these changes, your template would return a string, not a list. No matter how hard you try.

(Note - I changed your hs_color output to a list by adding the braces. The way you had it was just 2 numbers with a \n between them)

This is a great replay; thanks!

Right now I’m stuck on something a lot sillier and more basic… even though in a service call I can change a light’s color with hs_color, in an automation I can’t…

- id: '1606613838555'
  alias: PurpleAir Changes Uplight Color
  description: ''
  trigger:
  - platform: state
    entity_id: sensor.purpleair_pm25
  condition: []
  action:
  - service: light.turn_on
    data:
      entity_id: light.sengled_e11_n1ea_50e10800_level_light_color_on_off
      brightness_pct: 100
      xy_color: [0.12,0.1]
  mode: single

Works… as in the automation gets loaded and works properly. BUT this doesn’t…

- id: '1606613838555'
  alias: PurpleAir Changes Uplight Color
  description: ''
  trigger:
  - platform: state
    entity_id: sensor.purpleair_pm25
  condition: []
  action:
  - service: light.turn_on
    data:
      entity_id: light.sengled_e11_n1ea_50e10800_level_light_color_on_off
      brightness_pct: 100
      hs_color: [120,100]
  mode: single

Part of me wants to figure it out, and part of me is just going to do the math to convert from hs to xy! But regardless, a big thanks for the harder part of the job (templates and namespaces).

That’s odd. The documentation does say hs_color is a list of floats. What happens if you try

hs_color: [120.0,100.0]

Or

hs_color:
  - 120.0
  - 100.0

Does it work then?

Yes, @jocnnor, floating point was the trick.

For posterity, I cleaned things up…

The automation:

- id: '1606613838555'
  alias: PurpleAir Changes Uplight Color
  description: ''
  trigger:
  - platform: state
    entity_id: sensor.purpleair_pm25
  condition: []
  action:
  - service: light.turn_on
    data:
      entity_id: light.sengled_e11_n1ea_50e10800_level_light_color_on_off
      hs_color: [ '{{ states("sensor.pm25_hue") }}' ,100.0]
  mode: single

and the sensor:

  - platform: template
    sensors:
      pm25_hue:
        friendly_name: "Purple 2.5 Hue"
        value_template: >-
          {% if (states("sensor.purpleair_pm25") | int) < 50 %}
            {{ 120-4*(states("sensor.purpleair_pm25") | float) }}
          {% elif (states("sensor.purpleair_pm25") | int) < 150 %}
            {{ [60-0.6*(states("sensor.purpleair_pm25")|int),1]|max|float }}
          {% else %}
            {{ 300.0 }}
          {% endif %}
1 Like

TIP:
If you use a variable within the template, it helps to make it a bit more legible:

  - platform: template
    sensors:
      pm25_hue:
        friendly_name: "Purple 2.5 Hue"
        value_template: >-
          {% set pm = states('sensor.purpleair_pm25') | float %}
          {% if pm < 50 %}
            {{ 120 - 4 * pm }}
          {% elif pm < 150 %}
            {{ [ 60 - 0.6 * pm, 1] | max }}
          {% else %}
            300.0
          {% endif %}

Thank you, indeed @123. I tweaked the colors a bit (here in case someone else wants to match a bulb with PurpleAir)


  - platform: template
    sensors:
      pm25_hue:
        friendly_name: "Purple 2.5 Hue"
        value_template: >-
          {% set pm = states('sensor.purpleair_pm25') | float %}
          {% if pm < 50 %}
            {{ 120 - 1.2 * pm }}
          {% elif pm < 150 %}
            {{ [ 60 - 0.6 * (pm-50), 1] | max }}
          {% else %}
            300.0
          {% endif %}