What's Wrong With My Script?

Hi everyone,

I have the following script:

photons_apply_theme_manual:
  sequence:
    - service: rest_command.photons_apply_theme
      data_template: >-
        {% if is_state('input_select.lifx_devices_all', 'Tiles') %}
          colors: {{ states("sensor.lifx_themes") }}
          brightness: {{ state_attr("light.tiles", "brightness")|float / 256 | round(2) }}
          label: "Tiles"
        {% elif is_state('input_select.lifx_devices_all', 'Candle') %}
          colors: {{ states("sensor.lifx_themes") }}
          brightness: {{ state_attr("light.candle", "brightness")|float / 256 | round(2) }}
          label: "Candle"
        {% elif is_state('input_select.lifx_devices_all', 'Beam') %}
          colors: {{ states("sensor.lifx_themes") }}
          brightness: {{ state_attr("light.beam", "brightness")|float / 256 | round(2) }}
          label: "Beam"
        {% elif is_state('input_select.lifx_devices_all', 'TV Z Strip') %}
          colors: {{ states("sensor.lifx_themes") }}
          brightness: {{ state_attr("light.tv_z_strip", "brightness")|float / 256 | round(2) }}
          label: "TV Z Strip"
        {% elif is_state('input_select.lifx_devices_all', 'Computer Z Strip') %}
          colors: {{ states("sensor.lifx_themes") }}
          brightness: {{ state_attr("light.computer_z_strip", "brightness")|float / 256 | round(2) }}
          label: "Computer Z Strip"
        {% elif is_state('input_select.lifx_devices_all', 'All') %}
          script.photons_apply_theme_all
        {% endif %}

Basically, I have this rest_command with template values in it here:

photons_apply_theme:
  url: 'http://192.168.1.205:6100/v1/lifx/command'
  method: "put"
  payload: '{"command": "apply_theme", "args": {"theme_options": {"colors": {{ colors }}, "overrides": {"brightness": {{ brightness }} } }, "matcher": {"label": {{ label }} } }}'

But I want to change the template values that go into it based on the state of input_select.lifx_devices_all. The problem is when I reload my script I get this error:

Invalid config for [script]: expected dict for dictionary value @ data['sequence'][0]['data_template']. Got None. (See /config/configuration.yaml, line 382).

All of your templates lack outer quotes.

For example, this:

colors: {{ states("sensor.lifx_themes") }}

should be this:

colors: '{{ states("sensor.lifx_themes") }}'

If you use double-quotes inside the template (which you have) then you must use single quotes outside the template (and vice-versa).

You don’t need outer quotes if the template employs the > line-continuation character. in other words, this is valid:

colors: >
  {{ states("sensor.lifx_themes") }}

In addition, the last line of your if-elif chain doesn’t appear to be valid. Each elif supplies three variables to the rest_command (colors, brightness, label) but the last one doesn’t and attempts to supply the name of a script to the rest_command. If you thought it would execute the script, it won’t because data_template is meant to supply additional information to the service (i.e. to rest_command.photons_apply_theme).

I changed my script to this:

photons_apply_theme_manual:
  sequence:
    - service: rest_command.photons_apply_theme
      data_template: >-
        {% if is_state('input_select.lifx_devices_all', 'Tiles') %}
          colors: >
            {{ states("sensor.lifx_themes") }}
          brightness: '{{ state_attr("light.tiles", "brightness")|float / 256 | round(2) }}'
          label: "Tiles"
        {% elif is_state('input_select.lifx_devices_all', 'Candle') %}
          colors: >
            {{ states("sensor.lifx_themes") }}
          brightness: '{{ state_attr("light.candle", "brightness")|float / 256 | round(2) }}'
          label: "Candle"
        {% elif is_state('input_select.lifx_devices_all', 'Beam') %}
          colors: >
            {{ states("sensor.lifx_themes") }}
          brightness: '{{ state_attr("light.beam", "brightness")|float / 256 | round(2) }}'
          label: "Beam"
        {% elif is_state('input_select.lifx_devices_all', 'TV Z Strip') %}
          colors: >
            {{ states("sensor.lifx_themes") }}
          brightness: '{{ state_attr("light.tv_z_strip", "brightness")|float / 256 | round(2) }}'
          label: "TV Z Strip"
        {% elif is_state('input_select.lifx_devices_all', 'Computer Z Strip') %}
          colors: >
            {{ states("sensor.lifx_themes") }}
          brightness: '{{ state_attr("light.computer_z_strip", "brightness")|float / 256 | round(2) }}'
          label: "Computer Z Strip"
        {% endif %}

But I’m still getting the same error… Any thoughts? Also, I removed the last elif that calls another script, but I’m trying to think of a way to implement that. Basically, what I want to do is if the value of the input_select is anything but “All”, then call the REST_command with the data_template I already have, otherwise run script.photons_apply_theme_all.

Well there is also the important error I overlooked to mention:

  • You can’t use templates to generate options.

A template is for computing a value assigned to an option.

some_option: "{{ template to compute the option's value }}"

It cannot be used to generate an option. This is invalid:

{% if something is true %}
  this_option: cat
  that_option: dog
{% else %}
  this_option: bat
  that_option: rat
{% endif %}

You’re going to need to rethink the entire approach. Here’s what I suggest you consider doing.

photons_apply_theme_manual:
  sequence:
    - variables:
        device: "{{ states('input_select.lifx_devices_all') }}"
        entity: "light.{{ device.replace(' ', '_') | lower }}"
    - service: rest_command.photons_apply_theme
      data:
        colors: "{{ states('sensor.lifx_themes') }}"
        brightness: "{{ (state_attr(entity, 'brightness')|float / 256) | round(2) }}"
        label: "{{ device }}"

I see, so the part that’s wrong is when I get the state_attr “brightness” from my device? Which is “generating an option” and therefore invalid because you can’t do that in templates?

And this is only the case in a data/service/etc template? Because when using the same template in the below script, it works perfectly:

photons_theme_update_tiles:
  sequence:
    - service: rest_command.photons_apply_theme
      data:
        colors: '{{ states("sensor.lifx_month") }}'
        brightness: '{{ state_attr("light.tiles", "brightness")|float / 256 }}'
        label: '"Tiles"'

Also, this solution you proposed looks very nice, thank you. However, I am still unsure how to incorporate the last case where a script is run when input_select.lifx_devices_all is selected. See, I have 5 options for lights and 1 option for “All lights”. With your solution, it will work perfectly for the 5 lights, but if I select “All”, it’s going to try to send a REST command where the entity you specified is light.all, which doesn’t exist. I am struggling to conceptualize how I would use your solution for 5 of the input_select options, and just run a simple script for the last option.

If it matters, that script I want to run is actually just running this REST command 5 times, inputting the data for each light in succession, instead of just one.

That “works perfectly” because the templates are used to compute values for options and they are not attempting to generate options.

This is fine:

option: "{{ template creating a value for the option }}"

this is not:

"{{ template creating options and their values }}"

Use choose to make a decision whether to execute the script or the rest_command.

photons_apply_theme_manual:
  sequence:
    - variables:
        device: "{{ states('input_select.lifx_devices_all') }}"
        entity: "light.{{ device.replace(' ', '_') | lower }}"
    - choose:
        - conditions: "{{ device == 'All' }}"
          sequence:
             - service: script.photons_apply_theme_all
      default:
        - service: rest_command.photons_apply_theme
          data:
            colors: "{{ states('sensor.lifx_themes') }}"
            brightness: "{{ (state_attr(entity, 'brightness')|float / 256) | round(2) }}"
            label: "{{ device }}"

Perfect! Thanks so much for your help.

1 Like