Pick random light colors from small list, but do not repeat

I have an automation that runs every 5 mins to change the colors of four lights. Its work fine, but Id like to make sure a color isnt repeated.

Seems like I need a variable to know what the previous random pick was…and remove from the list.

Could someone point me in the right direction?

action:
  - service: light.turn_on
    data:
      color_name: >-
        {{ ['red', 'blue', 'green', 'yellow', 'orange', 'magneta', 'purple'] |
        random }}
      transition: 2
      brightness_pct: 50
    target:
      entity_id: light.smart_led_bulb_7
  - service: light.turn_on
    data:
      color_name: >-
        {{ ['red', 'blue', 'green', 'yellow', 'orange', 'magneta', 'purple'] |
        random }}
      transition: 2
      brightness_pct: 50
    target:
      entity_id: light.smart_led_bulb_8
  - service: light.turn_on
    data:
      color_name: >-
        {{ ['red', 'blue', 'green', 'yellow', 'orange', 'magneta', 'purple'] |
        random }}
      transition: 2
      brightness_pct: 50
    target:
      entity_id: light.smart_led_bulb_9
  - service: light.turn_on
    data:
      color_name: >-
        {{ ['red', 'blue', 'green', 'yellow', 'orange', 'magneta', 'purple'] |
        random }}
      transition: 2
      brightness_pct: 50
    target:
      entity_id: light.smart_led_bulb_10

A common programming way to do this is to sort the list randomly, and then take each one in order. When you get to the end of the list, sort it again. You could probably translate to an HA automation in conjunction with a text_input to store the values, but it would be simpler if you’re also using Node Red.

Having said that, the way I rotate random colors in Node Red is to randomize each of RGB between 0 and 255, and then randomly set one of them to 0. Without the last step, and with all three having values, it tended to come out white-ish too often. If you wanted to ensure adjacent colors weren’t too similar, you could just rotate which one got set to zero, along the lines of that below (the template could probably be better).

action:
  - service: light.turn_on
    data:
      rgb_color: >-
        {%- set rgb = state_attr('light.entrance', 'rgb_color') -%}
        {%- set multiply = [0, 1, 1] -%}
        {%- if rgb[0] == 0 %}
          {%- set multiply = [1, 0, 1]-%}
        {%- elif rgb[1] == 0 %}
          {%- set multiply = [1, 1, 0] -%}
        {%- endif -%}
        {%- set rgb = [(range(1, 255) | random) * multiply[0], 
                      (range(1, 255) | random) * multiply[1],
                      (range(1, 255) | random) * multiply[2]] %}
        {{ rgb }}
      transition: 2
      brightness_pct: 50
    target:
      entity_id: light.entrance
1 Like

I’m specifically trying to stay with a small set of defined colors for this particular application…thinking it would be easier to work with a list…but i’m getting stuck on list functions.

Here is what I have in Developer Tools

{%- set all_colors = ('red', 'blue', 'green', 'yellow', 'orange', 'magneta', 'purple') -%}
{%- set color = (all_colors | random) -%}
{{ color }}
{%- set all_colors = (all_colors | replace(color,'')) -%}
{{ all_colors }}

But I cant figure out how to remove the list item = ‘’

Even if I could, it seems as thought the all_colors variable is local to the service call, so:

action:
  - service: light.turn_on
    data:
      color_name: >-
        {{ color }}
      transition: 2
      brightness_pct: 50
    target:
      entity_id: light.smart_led_bulb_7
  - service: light.turn_on
    data:
      color_name: >-
        {{ color  }}
      transition: 2
      brightness_pct: 50
    target:
      entity_id: light.smart_led_bulb_8

isn’t going to work.

My idea was to start the automation with all the colors, then remove the used ones, one at a time, as lights are turned on.

My searching seems to be pointing me to needing to create an input_text
https://community.home-assistant.io/t/on-each-run-pick-random-element-from-list-remove-from-list-if-list-empty-reset-list-to-original-contents/268248

– which I can do, but I was hoping there was an easier way to accomplish this.