Custom LIFX Animate Theme effect script

This script is intended to work with groups of individual bulbs, it won’t mimic the tile, beam or lifx z animate theme effect. I decided to upload it since I’m really impressed with the results and how close to the actual LIFX Animate theme it performs and I can’t find anything related to this effect in the forums. As you might know Animate theme requires your LIFX App to be running in order to work, so this script would solve that, plus many other advantatges (selecting a trigger, for example, rather than going to the App every time)

Let’s get started. In order to get the same randomness as the original effect both in color selection and in transition duration of the fade effects, we need to define two random sensors, one for each value in our configuration.yaml:
( we just need to define one sensor ‘sensor.segundos’, look post number 4 for the best solution )

sensor:
  - platform: random
    name: segundos
    minimum: 2
    maximum: 5
  - platform: random
    name: color intense
    minimum: 1
    maximum: 4

So the fade effects will transition between 2-5 seconds (‘segundos’ in spanish) and the color palette contains, in this case, 4 colors. In this particular example we are going to run this effect across 4 lights.

Once done that, let’s go to the actual script:

animated_intense:
  alias: animated intense
  sequence:
  - service: lifx.set_state
    entity_id: light.number_1
    data_template:
      color_name: >
        {% if is_state('sensor.color_intense', '1')%}
          blue
        {% elif is_state('sensor.color_intense', '2')%}
          midnightblue
        {% elif is_state('sensor.color_intense', '3')%}
          mediumspringgreen
        {% elif is_state('sensor.color_intense', '4')%}
          magenta
        {% endif %}
      transition: "{{ states('sensor.segundos')}}"
  - service: homeassistant.update_entity
    entity_id: sensor.color_intense
  - service: lifx.set_state
    entity_id: light.number_2
    data_template:
      color_name: >
        {% if is_state('sensor.color_intense', '1')%}
          blue
        {% elif is_state('sensor.color_intense', '2')%}
          midnightblue
        {% elif is_state('sensor.color_intense', '3')%}
          mediumspringgreen
        {% elif is_state('sensor.color_intense', '4')%}
          magenta
        {% endif %}
      transition: "{{ states('sensor.segundos')}}"
  - service: homeassistant.update_entity
    entity_id: sensor.color_intense
  - service: lifx.set_state
    entity_id: light.number_3
    data_template:
      color_name: >
        {% if is_state('sensor.color_intense', '1')%}
          blue
        {% elif is_state('sensor.color_intense', '2')%}
          midnightblue
        {% elif is_state('sensor.color_intense', '3')%}
          mediumspringgreen
        {% elif is_state('sensor.color_intense', '4')%}
          magenta
        {% endif %}
      transition: "{{ states('sensor.segundos')}}"
  - service: homeassistant.update_entity
    entity_id: sensor.color_intense
  - service: lifx.set_state
    entity_id: light.number_4
    data_template:
      color_name: >
        {% if is_state('sensor.color_intense', '1')%}
          blue
        {% elif is_state('sensor.color_intense', '2')%}
          midnightblue
        {% elif is_state('sensor.color_intense', '3')%}
          mediumspringgreen
        {% elif is_state('sensor.color_intense', '4')%}
          magenta
        {% endif %}
      transition: "{{ states('sensor.segundos')}}"
  - service: homeassistant.update_entity
    entity_id: sensor.color_intense
  - delay:
      seconds: "{{ states('sensor.segundos')}}"
  - service: homeassistant.update_entity
    entity_id: sensor.segundos
  - condition: template
    value_template: "{{ is_state('input_select.party_scenes_verano', 'Modo Intense Verano') and is_state('input_select.modo', 'Party')}}"
  - service: script.turn_on
    entity_id: script.repeat_intense

It’s fairly evident what’s taking place there. lifx.set_state picks the color depending on the state of our random sensor.color_intense and transitions depending on the state of our sensor.segundos (sensor.seconds for you probably).

take note of this service call that takes place between every lifx.set_state call:

  - service: homeassistant.update_entity
    entity_id: sensor.color_intense

If you don’t do that, your sensor.color_intense will remain with the same value for 30 seconds or more and all your lights will fade the same color. By calling that service you are forcing the sensor to change its value randomly between every lifx.set_state call and therefore chaging color selection too.

Note that in the lifx.set_state data we are using the attribute transition with the value of the sensor we previously created:

  - service: lifx.set_state
    entity_id: light.number_4
    data_template:
      color_name: >
        {% if is_state('sensor.color_intense', '1')%}
          blue
        {% elif is_state('sensor.color_intense', '2')%}
          midnightblue
        {% elif is_state('sensor.color_intense', '3')%}
          mediumspringgreen
        {% elif is_state('sensor.color_intense', '4')%}
          magenta
        {% endif %}
      transition: "{{ states('sensor.segundos')}}"

which we will force to change exactly as we did with the other sensor after a delay of the same value as the transitions previously called, in order to allow them to finish, that is:

  - delay:
      seconds: "{{ states('sensor.segundos')}}"
  - service: homeassistant.update_entity
    entity_id: sensor.segundos

we add a delay of the same value as all the previous transitions at the end of all the lifx.set_state calls to allow them to finish their fade effect, and right after that we force the sensor.segundos (seconds) to change again for the next round. To restart the script and keep it running I used:

  - service: script.turn_on
    entity_id: script.repeat_intense

Given script.repeat_intense is nothing more than:

repeat_intense:
  alias: Repeat Intense
  sequence:
  - service: script.turn_on
    entity_id: script.animated_intense

so this way it keeps cycling endlessly. The condition showing in the bottom of the script is really something completely up to you:

  - condition: template
    value_template: "{{ is_state('input_select.party_scenes_verano', 'Modo Intense Verano') and is_state('input_select.modo', 'Party')}}"
  - service: script.turn_on
    entity_id: script.repeat_intense

I use it because I otherwise find it hard to stop the script. Putting that condition there will automatically stop the script when those conditions aren’t met. You could use an input boolean there, some other device state or whichever condition you want for it to stop. I tried using the script.turn_off service but it hasn’t showed to be too reliable, It won’t always stop the script.

final notes, I used the ‘color_name’ attribute instead of rgb_color or hs_color because I couldn’t get it to work with templates, dunno why. Thankfully the color_name palette is pretty wide (find it here: “https://www.w3.org/TR/css-color-3/#svg-color”) and It has satisfied my needs for the moment, but if anyone get this script working with hs_color or rgb_color, I would very much appreciate sharing the code.

if you want your lights to first turn on, use the ‘power: true’ attribute, otherwise they’ll remain in the state they currently are.

If you are using other bulb brand (I believe philips is the only one allowing transitions), just use the light.turn_on service.

If you just copy and paste this script with your light entities, it should give a pretty decent Intense Animate theme, pretty close to the lifx original. I wonder if you can tell the difference.

Hope you like it

If you’re interested, you can eliminate the two random sensors and incorporate random colors and seconds directly within the script. That reduces the script’s length because you don’t have to update the random sensors to make them change value.

animated_intense:
  alias: animated intense
  sequence:
  - service: lifx.set_state
    entity_id: light.number_1
    data_template:
      color_name: "{{ ['blue', 'midnightblue', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ range(2, 6) | random }}"
  - service: lifx.set_state
    entity_id: light.number_2
    data_template:
      color_name: "{{ ['blue', 'midnightblue', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ range(2, 6) | random }}"
  - service: lifx.set_state
    entity_id: light.number_3
    data_template:
      color_name: "{{ ['blue', 'midnightblue', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ range(2, 6) | random }}"
  - service: lifx.set_state
    entity_id: light.number_4
    data_template:
      color_name: "{{ ['blue', 'midnightblue', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ range(2, 6) | random }}"
  - delay:
      seconds: "{{ range(2, 6) | random }}"
  - condition: template
    value_template: "{{ is_state('input_select.party_scenes_verano', 'Modo Intense Verano') and is_state('input_select.modo', 'Party')}}"
  - service: script.turn_on
    entity_id: script.repeat_intense
1 Like

Thanks a lot, I’ll give it a shot

do you know how to get it to work with rgb_color or hs_color?

is there any place where I can learn all filters, templates, the {% set %} and {% for %} tools? the documentation feels to cryptic for me, I’m just starting off…

thanks a lot

one little problem I have with your script, I want the four transitions and the delay to be of the exact same value until the next round… how could I do that?

I ended up doing a mix of the two scripts, I like transitions to complete before I send another call.

animated_intense_2:
  alias: animated intense 2
  sequence:
  - service: lifx.set_state
    entity_id: light.number_1
    data_template:
      color_name: "{{ ['blue', 'blue', 'midnightblue', 'midnightblue', 'mediumspringgreen', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ states('sensor.segundos')}}"
  - service: lifx.set_state
    entity_id: light.number_2
    data_template:
      color_name: "{{ ['blue', 'blue', 'midnightblue', 'midnightblue', 'mediumspringgreen', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ states('sensor.segundos')}}"
  - service: lifx.set_state
    entity_id: light.number_3
    data_template:
      color_name: "{{ ['blue', 'blue', 'midnightblue', 'midnightblue', 'mediumspringgreen', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ states('sensor.segundos')}}"
  - service: lifx.set_state
    entity_id: light.number_4
    data_template:
      color_name: "{{ ['blue', 'blue', 'midnightblue', 'midnightblue', 'mediumspringgreen', 'mediumspringgreen', 'magenta'] | random }}"
      transition: "{{ states('sensor.segundos')}}"
  - delay:
      seconds: "{{ states('sensor.segundos')}}"
  - service: homeassistant.update_entity
    entity_id: sensor.segundos
  - service: script.turn_on
    entity_id: script.repeat_intense_2

magenta appears one time while the other colours appear two times on purpose because I like magenta less

The rgb_color option expects a list containing three values between 0 and 255. In YAML you can define a list like this:

  rgb_color:
   - 125
   - 85
   - 210

or like this:

  rgb_color: [ 125, 85, 210 ]

If you need to template the values then the two formats look like this:

  rgb_color:
   - "{{ red template }}"
   - "{{ green template }}"
   - "{{ blue template }}"
  rgb_color: [  "{{ red template }}",  "{{ green template }}", "{{ blue template }}" ]

Here’s what it would look like for your requirements using rgb_color and hs_color:

  - service: lifx.set_state
    entity_id: light.number_1
    data_template:
      rgb_color: 
        - "{{ range(0, 256) | random }}"
        - "{{ range(0, 256) | random }}"
        - "{{ range(0, 256) | random }}"
      transition: "{{ states('sensor.segundos')}}"
  - service: lifx.set_state
    entity_id: light.number_1
    data_template:
      hs_color: 
        - "{{ range(0, 361) | random }}"
        - "{{ range(0, 101) | random }}"
      transition: "{{ states('sensor.segundos')}}"

Take note that the range() function’s end-value is always one more than you need. So if you need a number from 0 to 255 you would use range(0, 256).

your first suggestion is the way to go, I believe… thank you very much

definetely remove the color selection sensor and just go with the random filter

color_name attribute is much easier to work with and it’s decently wide, it would be a pain to set a specific saturation for a specific hue randomly

Thanks for sharing this. I’ve adapted it a bit for use with areas, and leveraging script fields and variables. I’m happy to hear any recommendations!


# LIFX ANIMATION LOOP
lifx_animation_loop:
  alias: LIFX Animation Loop
  description: Start Animation Effect loop on LIFX lights.
  mode: parallel
  max: 4
  icon: mdi:blur
  variables:
    transition_min: 3
    transition_max: 5
    colors: "['blue', 'midnightblue', 'mediumspringgreen', 'magenta']"
    area: "Living Room"
  fields:
    area:
      description: The name of the room or area to run the animation effect on. [required]
      example: Living Room
      required: false
    colors:
      description: A list of colors to use in this animation sequence. [optional]
      example: "['blue', 'midnightblue', 'mediumspringgreen', 'magenta', 'purple']"
      required: false
    transition_min:
      description: Minimum transition time in seconds. [optional] (default is 3)
      example: 4
      required: false
    transition_max:
      description: Max transition time in seconds. [optional] (default is 5)
      example: 5
      required: false
  sequence:
  - service: lifx.set_state
    data_template:
      color_name: '{{ colors|random }}'
      transition: '{{ range(transition_min|int, transition_max|int)|random }}'
      area_id: '{{ (area|lower|replace(" ", "")|trim) }}'
  - delay:
      seconds: "{{ transition_max }}"
  - condition: template
    value_template: "{% set check_entity = 'input_boolean.animate_'+(area|lower|replace(' ', '_')|trim)+'_lights_fx' %}{{ is_state(check_entity, 'on') }}"
  - service: script.turn_on
    target:
      entity_id: script.lifx_animation_loop
    data:
      variables:
        transition_min: '{{ transition_min }}'
        transition_max: '{{ transition_max }}'
        colors: '{{ colors }}'
        area: '{{ area }}'
1 Like

there’s definetely a lot of room to improve it and that’s one way ;), beautiful

Would someone be able to explain to me how to implement this? I’ve only recently started using HA and this seems above what I can currently achieve, Today I made my first if action to turn an lifx buble on and colour cycle but this seems like it would be better because I can choose the colours it goes between right?

currently colour cycle is a bit rubbish as it goes to white too often