A Script that does work but the code doesn't look sexy

Hi,

I have pool lights which can be set to color by switching it off and on until you have the right color. (It comes with a remote as well but that only works if you are really standing next to the lights).

To select the color I made a text drop box to pick the color and then I run a script based on the selection which switches on/off the lights until the preferred color appears. Really simple. This is how it looks like:
image
And the script is like this:

alias: Pool Light Color
sequence:
  - if:
      - condition: state
        entity_id: input_select.colour_selector
        state: Red
    then:
      - repeat:
          count: 1
          sequence:
            - service: switch.turn_off
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
            - service: switch.turn_on
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
  - if:
      - condition: state
        entity_id: input_select.colour_selector
        state: Green
    then:
      - repeat:
          count: 2
          sequence:
            - service: switch.turn_off
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
            - service: switch.turn_on
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
  - if:
      - condition: state
        entity_id: input_select.colour_selector
        state: Blue
    then:
      - repeat:
          count: 3
          sequence:
            - service: switch.turn_off
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
            - service: switch.turn_on
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
  - if:
      - condition: state
        entity_id: input_select.colour_selector
        state: Yellow
    then:
      - repeat:
          count: 4
          sequence:
            - service: switch.turn_off
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
            - service: switch.turn_on
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
  - if:
      - condition: state
        entity_id: input_select.colour_selector
        state: Pink
    then:
      - repeat:
          count: 5
          sequence:
            - service: switch.turn_off
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
            - service: switch.turn_on
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
  - if:
      - condition: state
        entity_id: input_select.colour_selector
        state: Cyan
    then:
      - repeat:
          count: 6
          sequence:
            - service: switch.turn_off
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
            - service: switch.turn_on
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
  - if:
      - condition: state
        entity_id: input_select.colour_selector
        state: White
    then:
      - repeat:
          count: 7
          sequence:
            - service: switch.turn_off
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
            - service: switch.turn_on
              data: {}
              target:
                entity_id: switch.sonoff_100079182a
            - delay:
                hours: 0
                minutes: 0
                seconds: 1
                milliseconds: 0
mode: single
icon: mdi:wall-sconce-round-outline

For those who are interested I would like that once the color is selected the script runs directly after without manually starting the script. Secondly I would like to assign a variable to count like

count: x

Where is x the number of repeats based on the selected color. And to be honest I don’t know how to do that…

Lets first answer this

Do an automation:

alias: Change pool color
trigger:
  - platform: state
    entity_id: input_select.colour_selector
action:
  - service: script.turn_on
    target:
      entity_id: script.pool_light_color

And you can simplify like this (not tested)

alias: Pool Light Color
sequence:
  - variables:
      counts:
        Red: 1
        Green: 2
        Blue: 3
        Yellow: 4
        Pink: 5
        Cyan: 6
        White: 7
  - variables:
      selected_color: "{{ states('input_select.colour_selector') }}"
  - repeat:
      count: "{{ counts[selected_color] }}"
      sequence:
        - service: switch.turn_off
          target:
            entity_id: switch.sonoff_100079182a
        - delay:
            hours: 0
            minutes: 0
            seconds: 1
            milliseconds: 0
        - service: switch.turn_on
          target:
            entity_id: switch.sonoff_100079182a
        - delay:
            hours: 0
            minutes: 0
            seconds: 1
            milliseconds: 0
mode: single
icon: mdi:wall-sconce-round-outline

Done. Works!! Thank you. Very straight forward!

Yes and this is exactly what I wanted. A neat piece of code and this is much better then mine! Super cool! Thanks a lot!

Gonna try it now and let you know!

EDIT: Great works perfectly. From the front-end side neat and from the coding side pretty slick!! And I learned something (not unimportant)!

If you’re interested, you can reduce the script to this:

alias: Pool Light Color
sequence:
  - repeat:
      count: >
        {{ ['Red','Green','Blue','Yellow','Pink','Cyan','White'].index(states('input_select.colour_selector')) + 1 }}
      sequence:
        - repeat:
            for_each:
              - 'off'
              - 'on'
            sequence:
              - service: 'switch.turn_{{ repeat.item }}'
                target:
                  entity_id: switch.sonoff_100079182a
              - delay:
                  seconds: 1
mode: single
icon: mdi:wall-sconce-round-outline

  • It uses a list to store the colors. A color’s position in the list (its index value) determines the number of iterations of the repeat count.

  • It employs a repeat for_each to perform the sequential switch.turn_off and switch.turn_on actions.

I love this one as well. It’s even shorter. I still need a bit of time to thinks this one through though!

I would never have come up with this :exploding_head:

I like Taras for_each trick, and even if the array is more concise, I prefer my version from a readability point of view. Everyone’s taste is different.

To explain Taras’ solution: array index starts with 0 so Red = 0, Green = 1, … Therefore taking the index and adding 1 is giving you the count you’d like.
The for each, for every iteration of the count, will go off then on, and Taras is using that value in the service call, to do the 2 actions of your original sequence into one.

Feel free to mix :slight_smile:. I’m taking Taras for_each.

alias: Pool Light Color
sequence:
  - variables:
      counts:
        Red: 1
        Green: 2
        Blue: 3
        Yellow: 4
        Pink: 5
        Cyan: 6
        White: 7
  - repeat:
      count: "{{ counts[states('input_select.colour_selector')] }}"
      sequence:
        - repeat:
            for_each:
              - 'off'
              - 'on'
            sequence:
              - service: 'switch.turn_{{ repeat.item }}'
                target:
                  entity_id: switch.sonoff_100079182a
              - delay:
                  seconds: 1
mode: single
icon: mdi:wall-sconce-round-outline

But both solutions and everything in between are viable :slight_smile:

Your seven colors have integer values starting at 1 and ending at 7. That makes them a good fit for storage in a list. If the colors had non-sequential values, a dictionary would be better.

A single template defines the list of colors and gets a color’s index value.

{{ ['Red','Green','Blue','Yellow','Pink','Cyan','White'].index(states('input_select.colour_selector')) + 1 }}

The first item in a list has an index value of 0. That’s one less than the actual value we want for Red so that’s why the template adds 1 to the index value.

Another way to compensate for the list’s ‘zero-based index’ is to simply include a ‘dummy value’ in the ‘zeroth’ position. That’ll make Red have an index value of 1 so we no longer need to add 1.

{{ ['None','Red','Green','Blue','Yellow','Pink','Cyan','White'].index(states('input_select.colour_selector')) }}

If the template seems ‘too busy’, we can define the list separately, as a script variable in YAML.

alias: Pool Light Color
sequence:
  - variables:
      colors:
        - None
        - Red
        - Green
        - Blue
        - Yellow
        - Pink
        - Cyan
        - White
  - repeat:
      count: >
        {{ colors.index(states('input_select.colour_selector')) }}
      sequence:
        - repeat:
            for_each:
              - 'off'
              - 'on'
            sequence:
              - service: 'switch.turn_{{ repeat.item }}'
                target:
                  entity_id: switch.sonoff_100079182a
              - delay:
                  seconds: 1
mode: single
icon: mdi:wall-sconce-round-outline

As you can see, there are several ways to compose the script and which way you consider to be “sexy” depends on your personal preference.

References:
Python List Index

I agree that the for_each: solution is neat. It’s new to me and so you learn. From Readability point of view the last one is what I will use.

Thank you guys! :blush: How simple things can make your day!