Ashley’s Light Fader 2.0✨: fade lights and/or color temperature with your choice of easing (curves), including ease-in, ease-out, and ease-in-out

Most of my lights are from ikea, but I do have 2 that are from Philips Hue. All my lights are connected to a zigbee coordinator via z2mqtt. I have tested the Philips Hue bulb with the script and it does not behave like the ikea does. The Philips Hue bulb does turn back on at 1%.

Wondering if I need to update the ikea bulb firmware?
Current ikea gu10:

Firmware build date: 20220928
Firmware version: 2.3.095

Hi Ashley,
I have started using your script after you kindly responded in another post about a problem I was having. Your script has worked brilliantly to solve the issue of my light overloading from a tight loop and refusing to finish a fade.

When I looked at your script I wondered if you have ever considered doing RGB fades in addition to the color temperature fades? I was thinking that you already have most of the logic and it would just be a matter of applying it in triplicate. I wrote a very crude proof of concept that you can try if you’d like. (Clearly this is missing all of the special sauce that makes your script so popular.)

alias: Lights Fader with RGB
sequence:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ is_state(light_entity, 'off') }}"
        sequence:
          - data:
              entity_id: "{{ light_entity }}"
            action: light.turn_on
          - delay: "00:00:01"
  - variables:
      starting_rgb: >
        {{ starting_rgb if starting_rgb is defined else
        (state_attr(light_entity, 'rgb_color')[0], state_attr(light_entity,
        'rgb_color')[1], state_attr(light_entity, 'rgb_color')[2]) if
        state_attr(light_entity, 'rgb_color') is not none else (255, 255, 255)
        }}
      starting_brightness: >
        {{ starting_brightness if starting_brightness is defined else
        state_attr(light_entity, 'brightness') | int if state_attr(light_entity,
        'brightness') is not none else 255 }}
  - data:
      name: Lights Fader
      message: >-
        Captured or provided state: RGB: {{ starting_rgb }}, Brightness: {{
        starting_brightness }} for light: {{ light_entity }}
    action: logbook.log
  - repeat:
      count: "{{ steps | int }}"
      sequence:
        - data_template:
            entity_id: "{{ light_entity }}"
            rgb_color:
              - >-
                {{ (starting_rgb[0] + ((ending_rgb[0] - starting_rgb[0]) /
                steps) * repeat.index) | int }}
              - >-
                {{ (starting_rgb[1] + ((ending_rgb[1] - starting_rgb[1]) /
                steps) * repeat.index) | int }}
              - >-
                {{ (starting_rgb[2] + ((ending_rgb[2] - starting_rgb[2]) /
                steps) * repeat.index) | int }}
            brightness: >-
              {{ (starting_brightness + ((ending_brightness -
              starting_brightness) / steps) * repeat.index) | int }}
          action: light.turn_on
        - delay:
            milliseconds: "{{ (fade_duration / steps * 1000) | int }}"
variables:
  light_entity: "{{ light_entity }}"
  ending_rgb: "{{ ending_rgb | default([255,255,255]) }}"
  ending_brightness: "{{ ending_brightness | default(100) }}"
  fade_duration: "{{ fade_duration | default(20) }}"
  steps: "{{ steps | default(100) }}"
mode: single
description: >
  Fade between two RGB colors or fade from the current state of the light to a
  target RGB color
icon: mdi:color-helper

Then I just did a few very basic actions in an automation.

With Starting RGB and Brightness provided:

action: script.lights_fader_with_rgb
data:
  light_entity: light.master_led_strip
  starting_rgb: [170,13,5]
  starting_brightness: 1
  ending_rgb: [40,40,200]
  ending_brightness: 200
  fade_duration: 20
  steps: 30

Starting from the current state of the light:

action: script.lights_fader_with_rgb
data:
  light_entity: light.master_led_strip
  ending_rgb: [40,40,200]
  ending_brightness: 200
  fade_duration: 20
  steps: 30
1 Like

Hi, @RN-Say—and thanks so much for your kind words!

And thanks also for your detailed message, including even your proof-of-concept code (!). And as RGB fades go, while I can certainly understand the appeal there, it so happens that there are a couple of hitches that can make RGB fades potentially tricky—

  • It so happens that fading between two RGB colors by way a direct straight line can sometimes result in some odd midpoints. For instance, consider this color palette, which I just stumbled upon at color.adobe.com:

Let’s hypothetically suppose that someone had wanted to fade from the third color in that set (4, 191, 157) [light teal] to the fourth color in the set (242, 129, 87) [orange].

If one were to calculate a direct-line fade between those two RGB colors, the mathematical midpoint would be (123, 160, 122), which happens to be sort of a muddy green that doesn’t necessarily come across as being the intuitive midpoint of those two colors?


(screenshot via: rgbcolorpicker.com)

  • And the other sticky part about RGB fades—and this is actually even thornier than the previous quirk—is that there’s no clear means for handling things if someone were to try to fade from an RGB color to a Kelvin color temperature (or the other way: from a Kelvin color temperature to an RGB color). And that’s because—as @parautenbach aptly conveys in this earlier comment—there aren’t any consistent formulas available for converting from RGB to Kelvin (and from Kelvin to RGB):

All in all, I very much appreciate your idea, and if there were a way to make it work, I’d be rather tempted to give it a go! Unfortunately, though, I think that RGB fades might not quite be in the cards for this script.

Wow, just wow. When I first started in Home Assistant I wanted to do something like this but did not have the time to build it. Thank you!

1 Like

There’s a nice illustration in the first answer here: Using HSV might be a better option if you only have a start and end value. I’ve used RGB interpolation in some places, but I have multiple colour stops, so the linear/shortest path issue is less noticable.

1 Like

For colour fading I use this blueprint…

1 Like

Thanks bunches, @Noblewolf—that really means a lot! :rainbow:

2 Likes

Thanks for passing along that resource, @parautenbach!

And with that in hand, I could see that approach potentially helping quite substantially if someone had wanted to put together some code for RGB-to-RGB fades.

(Naturally, when it comes to Ashley’s Light Fader in particular, there would still be the sticky problem of what to do if someone were to attempt to fade from a Kelvin color temperature to an RGB value—or the other way around—but that’s not at all to take away from the value of what’s covered in that Stack Exchange thread that you had linked to about the HSV color space.)

2 Likes

Yeah, it’s different things, so I’d keep them apart. Colour temperature is only valid for black body radiation.

1 Like

Hi,
I am new to HA and is trying out several automation with my bedroom lights. Glad that I found such wonderful script for fader. I think I have missed something when creating the script. Here’s what it looks like…several error messages popped up and I can’t figure it out how I can assign a light to perform fading under “entity” as there aren’t any for me to pick.

@handcoding I am trying this fader script for the first time and I’m getting the following in my logs when I try to run it:

2024-11-11 08:15:26.727 INFO (MainThread) [homeassistant.components.automation.living_room_wake_up] Living room wake up: Running automation actions
2024-11-11 08:15:26.727 INFO (MainThread) [homeassistant.components.automation.living_room_wake_up] Living room wake up: Executing step call service
2024-11-11 08:15:26.728 INFO (MainThread) [homeassistant.components.script.ashley_s_light_fader] Ashley’s Light Fader: Running script sequence
2024-11-11 08:15:26.728 INFO (MainThread) [homeassistant.components.script.ashley_s_light_fader] Ashley’s Light Fader: Executing step setting variables
2024-11-11 08:15:26.738 INFO (MainThread) [homeassistant.components.script.ashley_s_light_fader] Ashley’s Light Fader: Executing step setting variables
2024-11-11 08:15:26.741 INFO (MainThread) [homeassistant.components.script.ashley_s_light_fader] Ashley’s Light Fader: If at step 5: Running script sequence
2024-11-11 08:15:26.741 INFO (MainThread) [homeassistant.components.script.ashley_s_light_fader] Ashley’s Light Fader: If at step 5: Executing step call service
2024-11-11 08:15:26.919 INFO (MainThread) [homeassistant.components.script.ashley_s_light_fader] Ashley’s Light Fader: Executing step setting variables
2024-11-11 08:15:26.925 ERROR (MainThread) [homeassistant.components.script.ashley_s_light_fader] Ashley’s Light Fader: Error executing script. Error rendering template for variables at pos 6: ZeroDivisionError: float division by zero
2024-11-11 08:15:26.929 ERROR (MainThread) [homeassistant.components.automation.living_room_wake_up] Living room wake up: Error executing script. Error rendering template for call_service at pos 1: ZeroDivisionError: float division by zero
2024-11-11 08:15:26.933 ERROR (MainThread) [homeassistant.components.automation.living_room_wake_up] Error while executing automation automation.living_room_wake_up: ZeroDivisionError: float division by zero

I’m using v2.0 of the script and the target entity is a group of Philips Hue bulbs integrated via the Hue Hub.

Any ideas on what I should try to resolve or troubleshoot the issue?

Thanks!

I’d like to run this automation script each day at dusk (which I know how to do) and set it to run until 23:00 (so the duration is obviously dynamic, depending on time of year). I’ve figured out how to calculate hours, minutes and seconds, but it seems I can’t use these in transitionTime (it won’t work):

action: script.ashley_s_light_fader
data:
  lampBrightnessScale: zeroToOneHundred
  easingTypeInput: linear
  endBrightnessPercent: 0
  endBrightnessEntityScale: zeroToOneHundred
  autoCancelThreshold: 10
  shouldStopIfTheLampIsTurnedOffDuringTheFade: true
  shouldResetTheStopEntityToOffAtStart: false
  shouldInvertTheValueOfTheStopEntity: false
  minimumStepDelayInMilliseconds: 100
  shouldTryToUseNativeLampTransitionsToo: false
  isDebugMode: true
  transitionTime:
    hours: {{ ((now().replace(hour=23, minute=0, second=0, microsecond=0) - now()).total_seconds() // 3600) | int if now().hour < 23 else 0 }}
    minutes: {{ (((now().replace(hour=23, minute=0, second=0, microsecond=0) - now()).total_seconds() % 3600) // 60) | int if now().hour < 23 else 0 }}
    seconds: {{ ((now().replace(hour=23, minute=0, second=0, microsecond=0) - now()).total_seconds() % 60) | int if now().hour < 23 else 0 }}
  light: light.shelly_dimmer2_26_1_2

Hi, @Thomas39!

Going by your screenshots, it looks like you might be trying to run the script directly from its script page?

In this case, Ashley’s Light Fader is meant to be run from another automation or from another script. So for example, you might try these steps:

  1. Create a new blank automation by going to SettingsAutomations & scenesCreate Automation.
  2. From there, under the Then Do section, choose Add Action.
  3. Then, within the Search action box, if you search for “Ashley”, the script should come up.

At that point, you should be able to apply the settings of your choosing.

(And if you might get stuck anywhere along the way, please feel free to reply here, and we’ll be happy to help you out!)

@2xaronl Out of curiosity, do things run any better if you target the bulbs individually? Or—as another potential idea—do things run any better if you were to instead group those bulbs through Home Assistant and then target them that way?

(Part of why I ask is because I’m not sure how well Hue-hub-based groups might work with Home Assistant.)

@vision2003 For reasons that seemingly make sense only to Home Assistant’s dev team, if you’re using a single-line template, you have to wrap that in quote marks, such as along these lines:

action: script.ashley_s_light_fader
data:
  lampBrightnessScale: zeroToOneHundred
  easingTypeInput: linear
  endBrightnessPercent: 0
  endBrightnessEntityScale: zeroToOneHundred
  autoCancelThreshold: 10
  shouldStopIfTheLampIsTurnedOffDuringTheFade: true
  shouldResetTheStopEntityToOffAtStart: false
  shouldInvertTheValueOfTheStopEntity: false
  minimumStepDelayInMilliseconds: 100
  shouldTryToUseNativeLampTransitionsToo: false
  isDebugMode: true
  transitionTime:
    hours: "{{ ((now().replace(hour=23, minute=0, second=0, microsecond=0) - now()).total_seconds() // 3600) | int if now().hour < 23 else 0 }}"
    minutes: "{{ (((now().replace(hour=23, minute=0, second=0, microsecond=0) - now()).total_seconds() % 3600) // 60) | int if now().hour < 23 else 0 }}"
    seconds: "{{ ((now().replace(hour=23, minute=0, second=0, microsecond=0) - now()).total_seconds() % 60) | int if now().hour < 23 else 0 }}"
  light: light.shelly_dimmer2_26_1_2

Perhaps give that a go?

(And if by any chance that doesn’t solve things, feel free to reply here, and I’ll be happy to help you look into other ideas.)

Working perfectly, thank you! :slight_smile:

1 Like

Ah—wonderful news! Happy to help!

Hi Ashley, I’m having dramas with the transition, it’s just not being smooth enough. Had a read through this forum, played around with the min delay settings etc, but it just doesn’t look smooth, no matter if it’s 2 seconds or 25 seconds, it all looks too ‘choppy’. When I use the automation where I just set the brightness property (or turn on off the light) the default transition on the light just works great, however not when I want to work with the transition durations using your script.

The following log is for 2second linear transition (as that looks probably the best considering the options), to 50% brightness, with 50ms delay (min)

2024-11-19 08:56:54.401 WARNING (MainThread) [homeassistant.components.system_log.external] linear easing type with 50 ms delay. remainingTimeInMilliseconds = 1850, and absoluteBrightnessSpan = 50
2024-11-19 08:56:54.402 WARNING (MainThread) [homeassistant.components.system_log.external] startBrightness = 0, endBrightness = 50, and processingDelayInMilliseconds = 144
2024-11-19 08:56:54.711 WARNING (MainThread) [homeassistant.components.system_log.external] Set Dining Lights All to 4 brightness. (Linear brightness would have been 4.) Delay is 50 ms. Elapsed time is 0.46 seconds. (endBrightness is 50.)
2024-11-19 08:56:54.914 WARNING (MainThread) [homeassistant.components.system_log.external] Set Dining Lights All to 13 brightness. (Linear brightness would have been 13.) Delay is 50 ms. Elapsed time is 0.67 seconds. (endBrightness is 50.)
2024-11-19 08:56:55.116 WARNING (MainThread) [homeassistant.components.system_log.external] Set Dining Lights All to 18 brightness. (Linear brightness would have been 18.) Delay is 50 ms. Elapsed time is 0.87 seconds. (endBrightness is 50.)
2024-11-19 08:56:55.318 WARNING (MainThread) [homeassistant.components.system_log.external] Set Dining Lights All to 23 brightness. (Linear brightness would have been 23.) Delay is 50 ms. Elapsed time is 1.07 seconds. (endBrightness is 50.)
...
...
...
2024-11-19 08:56:56.240 WARNING (MainThread) [homeassistant.components.system_log.external] Set Dining Lights All to 38 brightness. (Linear brightness would have been 38.) Delay is 50 ms. Elapsed time is 1.99 seconds. (endBrightness is 50.)
2024-11-19 08:56:56.449 WARNING (MainThread) [homeassistant.components.system_log.external] Set Dining Lights All to 50 brightness. Elapsed time is 2.2 seconds.

Any thoughts on how to make this work? Is that because the lights have their own transition predefined? I’m a bit lost, so thanks for any pointers

Hi Ashley,
I have recreated the script and now the call action is able to turn on the light, but it just wont fade. I linked the E27 bulbs to be switched on by TPlink Wifi Smart Plug. These are just normal non smart bulbs. No matter how long I set the fade in duration, it won’t happen. The bulbs just turn on and off as it is, no fading. Am I missing something ?