I have a handful of lights that don’t support transitions natively, and so I wrote a script for that.
Main features:
If you fade a lamp linearly between two brightness values, that can look unnatural to the human eye. So this light fader lets you choose between any of these 12 easing curves—and there’s also an option to have the script do its best to automatically select one of these easing curves for you.
( new for 2.0) You can now have the script fade between color temperatures too. And you can either simultaneously fade a lamp’s brightness and color temperature, or just fade its brightness, or just fade its color temperature.
You can (optionally) specify an end-color-temperature entity to have the script use that entity’s value for the fade’s end color temperature.
Some quick caveats: The script only supports color temperatures in Kelvin. And if you’d like to fade to a new color temperature, the lamp’s current color temperature also has to be defined in Kelvin units.
Then within Home Assistant, go to Settings → Automations & Scenes.
Select Scripts from the tabs across the top.
Click the Add Script button.
Once the blank script loads, open the “…” menu and choose Edit in YAML.
Select all the boilerplate text within the script, and delete that. Then paste in the code from your clipboard.
Lastly, choose Save Script.
(The write-up below the code goes over how you can use this script.)
How to put this script to use:
In any automation, choose Add Action → Call Service. Then if you start typing “Ashley”, this script should show up as the top item.
This script’s fields and options:
Light
The lamp’s internal brightness scale
If you happen to match this setting to the lamp’s internal brightness scale (0-to-255 or 0%-to-100%), the fade may be smoother. (If you’re not sure, you can just leave this as is.).
Fade time
Easing type
You can choose from 12 different easing types—or you can have the script try to automatically select an easing type. You can also see visualizers for each of these at Easings.net.
You can’t go wrong with any of the Ease-In-Out X easings as those will always look good whenever you’re fading between two nonzero brightness values.
The Ease-Out X easings often tend to look good if you’re fading up very quickly from zero.
The Ease-In X easings are mostly only included for completeness—those only tend to look good if you’re quickly fading to zero.
(optional) End brightness level
(optional) Use an entity instead for the end-brightness value?
You can optionally have the script instead use the value from an input-number helper, an input-select helper, an input-text helper, or a numeric sensor.
The end-brightness entity’s brightness scale (if used)
If you enable the previous option, select whether that entity represents brightness with a 0%-to-100% or 0-to-255 scale.
( new) (optional) End color temperature (in Kelvin)
( new) (optional) Use an entity instead for the end-color-temperature value?
You can optionally have the script instead use the value from an input-number helper, an input-select helper, an input-text helper, or a numeric sensor.
(optional) Brightness-change threshold that auto-cancels the fade
I don’t recommend setting this to anything less than 3 since not all lamps instantly reflect new brightness values. In my home, I personally use a value of around 10 most of the time.
( new) Cancel the fade if the lamp is turned off during the fade?
(Don’t worry—this feature is smart enough to not automatically cancel the fade at points when the lamp’s intended brightness might be zero, such as if the script were to be fading down to zero or fading up from zero.)
(optional) Stop if a certain entity is turned on during the fade?
You can optionally have the script keep an eye on an input boolean or a binary sensor. And if that entity is then turned on during the fade, the script will automatically stop. So for example, if you create a “Stop Everything” input boolean, and if you set that entity at this point, you can stop your fade at any time by turning on that “Stop Everything” entity.
(optional) Reset that “stop” entity to off just before starting the fade? (if used)
If you make use of the stop entity (above), you can also optionally have the script automatically reset that entity to “off” at the start of the fade. (By default, the script won’t change the value of the stop entity.)
( new) (optional) Stop only if the “stop” entity is instead turned OFF? (if used)
If you make use of the stop entity (above), you can optionally have the script automatically stop only if that entity is turned off during the fade.
( new) [experimental] If available, use the lamp’s native transitions too?
If the lamp natively supports transitions, you can have the script make use the lamp’s native transition effect when moving between brightness steps or color steps. When enabled, this has the possibility of offering even smoother fades if those brightness steps or color steps are very gradually spaced. (And while I use this feature in my own house, this feature isn’t as thoroughly tested as the script’s other features, so this feature is considered experimental for now.)
Minimum delay per step
If your lamp isn’t fading evenly—and especially if your lamp might appear to be pumping or ungracefully stair-stepping as it goes through the fade—you might try bumping this up a bit, such as to 150 ms or 200 ms (or possibly even a little higher).
Enable debugging mode?
If enabled, the script will output status messages to your Home Assistant log along the way.
Other bits:
If you have any questions or comments, feel free to tweet me at @FriendlyAshley or share any comments here.
This script is released under the Apache 2.0 license (same as Home Assistant).
Changelog:
2.0 (2023-11-13) — Added a bunch of new features:
You can now also fade the lamp’s color temperature either at the same time as (or separately from) fading the lamp’s brightness. ( @damru, @kvikindi & @ThatBlockyPenguin)
You can (optionally) have the script automatically cancel its fade if you turn off the lamp during the fade sequence.
If you make use of the stop entity, you can (optionally) have the script stop only when the stop entity is turned off (instead of the usual behavior where the script would stop only when the stop entity is turned on).
If you set the light to fade to 1%, and if the lamp’s internal brightness scale is 0-to-255, the script will infer that you’d like for the lamp to fade down to its lowest level, and so the script will automagically fade the light to 1/255 brightness. ( @ronnieSVK)
As an experimental feature, you can (optionally) have the script try to make use of the lamp’s native transition effect too, for potentially even smoother fades.
1.1 (2023-07-12) — Added an optional field for a stop entity, in which if that entity is set to “on,” the fader will automatically stop. Also added a few emoji to the GUI for readability. ( @damru)
1.03 (2023-06-29) — more graceful handling if starting brightness = ending brightness
Good morning. Awesome script. Converted everything to it.
I noticed these errors in my logs.
First:
Ashley’s Light Fader: Error executing script. Error rendering template for variables at pos 3: ZeroDivisionError: float division by zero
Followed by:
Kitchen lights on with lots of cloud cover already on adjustment: Parallel action at step 1: parallel 1: Error executing script. Error rendering template for call_service at pos 1: ZeroDivisionError: float division by zero
Kitchen lights on with lots of cloud cover already on adjustment: Parallel action at step 1: parallel 2: Error executing script. Error rendering template for call_service at pos 1: ZeroDivisionError: float division by zero
Kitchen lights on with lots of cloud cover already on adjustment: Parallel action at step 1: parallel 3: Error executing script. Error rendering template for call_service at pos 1: ZeroDivisionError: float division by zero
Kitchen lights on with lots of cloud cover already on adjustment: Error executing script. Error rendering template for parallel at pos 1: ZeroDivisionError: float division by zero
Ending with:
Error while executing automation automation.kitchen_lights_on_with_lots_of_cloud_cover_already_on_adjustment: ZeroDivisionError: float division by zero
I’m wondering if the issue here is the same discussed with @handcoding and @123 on my thread about light fader v2 going south for me after recent HA updates. The thought there was that if start and ending percentages are equal then it will return a zero which can’t be divided for a transition.
I noticed other automations using the same layout, different values, worked just fine after conversion.
EDIT: Traces shows that it successfully ran this at 7:10:29PM. Conditions changed and it triggered again at 7:20:03PM and 7:23:31 but erred with this in Traces:
Stopped because an error was encountered at June 27, 2023 at 7:20:03 PM (runtime: 0.22 seconds)
ZeroDivisionError: float division by zero
The sensor shows a spike which would have been too short to trigger a different adjustment automation for being brighter outside and the drop would’ve retriggered this.
Edit #2: Happened again today at a different time in the afternoon, and seems like the lights were at the brightness level already from a previous automation run. Figuring it’s a short time where the lux sensor gets more light and then suddenly less but not long enough to cause another automation to adjust lighting. So, it falls back and triggers this one again which ends up being a zero division.
Hi, @derekcentrico! Just to double-check, are you using the latest version of the script (which is v1.02 as of when I’m writing this)?
If you might not be sure which version you have, here’s how you can check—
First, open any of your automations where the the script is in use, and then scroll down to one of the instances where you’re calling the script.
From there, if you check the script’s description text—which is near the top of the script’s action box—it should hopefully say “v1.02”, such as like this:
I suppose the NOT condition is wrong, rather two ORs would be better to resolve this vs. worrying about an if then else check of the template to be sure start/end aren’t the same value to end up being zero.
@derekcentrico I believe that you’re correct that this issue can come about if a given light’s starting brightness and ending brightness are the same.
And while that may be an edge case, that’s nonetheless an edge case that my script should be able to gracefully handle. I’ll write an update to the script to handle that edge case, and I’ll see if I can release that update later today.
(And thank you for bringing this to my attention. Bug reports—while perhaps not as exciting as other types of feedback—are very much a valuable part of the development process.)
@derekcentrico By the way, I’ve just posted v1.03, which includes a fix for the edge case in which a lamp’s starting brightness were to be the same as its ending brightness.
And if you might run into any other weirdness, feel free to jot a comment here and I’ll be happy to chime in!
Cool beans. As I said super awesome script. I appreciate your willingness to tweak it for my odd scenario. I updated to 1.03 and reverted out my condition workaround. Thanks again!!!
That’s a really nice job here! Thanks @handcoding !
I’d have one request though.
In my case, I’m heavily relying on circadian lighting via Adaptive Lighting integration (ALI for short). Doing so, I’m facing a case where when turning a light on (from off state), I must disable the ALI before running the script. So far so good, but the thing is that the color temperature is completely off depending on when/how the light was turned off. So the light turns on, goes to target brightness, then I re-enable the ALI and the color only changes from there, which usually leads to eyes burning as it either changes from high to low temperature in the evening (eyes burning during dimming), or from low to high in the morning (eyes burning when temperature changes).
So, would it be possible to add an option to specify a color temperature ?
Thanks again for this awesome script
Hi, @damru—I stoked to hear that you’re digging the script!
I don’t happen to use Adaptive Lighting myself, but out of curiosity, when you’re about to do a fade, might it be possible to make use of Adaptive Lighting’s switch.adaptive_lighting_adapt_brightness_living_room switch to temporarily disable its brightness-adaptation feature (while leaving its color-adaptation feature enabled)?
Ah, yes, good catch! I completely missed it, thank you
And yes I’m digging it because it needs some love. The transition effects are really nice. This is a really handy script right and typically the type of things that could be part of the core if you ask me.
The only thing I’d miss is some kind of manual input_boolean which could be used to interrupt the script (instead of the % delta). I had that in a previous custom script, and it was really helpful when executing the script multiple times quickly on the same light. I used it to interrupt any running execution on the same light (I used to have 1 input_boolean per light managed by the script) before starting.
Basically:
if on, then set to off and wait for 'loop delay' (this way the other instance can stop)
set to on
while on, execute
Anyways, thank you again for the help and the script.
@damru While I’m not completely opposed to potentially adding that sort of feature, I think I may have a potential approach that could let you do that sort of thing now?
This involves using Trigger IDs, which are basically a technique that let you have multiple automation paths inside a single Home Assistant automation.
So for the sake of example, let’s suppose that you had a trigger ID for “bedroom lights turn on” that—when triggered—kick off a fade of the living room lights to 100%.
And then let’s suppose that you had a trigger ID for “dining room lights turn on” that—when triggered—kick off a fade of the living room lights to 10%.
And let’s suppose that you place both of those paths into one automation using trigger IDs, and you then set that automation’s mode to “restart” (which you can do through the automation’s “…” → “Change Mode” menu).
From there, if you turn on the bedroom lights, that will trigger the automation’s first path. And then—while that fade is still running—if you turn on the dining room lights, that should interrupt that first automation instance and then immediately begin running the automation’s second path.
I know that this might be a lot to take in, but I’d be quite happy to elaborate on any of this if it might help.
(And with all this being said, I’m still not necessarily opposed to perhaps adding that sort of feature. I just figured that I’d share this potential approach in case it might be able to take care of your use case even with the current state of the script.)
The use of TriggerID is ok in most cases.
And I know this is really edgy, by here is the issue that I ran into:
Prerequisites
The script must be able to run in parallel as you may trigger it from multiple automations at the same time, for different lights
Multiple automations targeting the same light. ex: 1 motion automation, 1 switch automation, 1 time-of-day automation. While each can be used with Restart mode to stop a run and start a new one, they also can be triggered at the same time
Each of these automations also do other things, so you cannot merge them into 1 do-it-all automation and split the sequences depending on Choose > TriggerID, or this will quickly become unmaintainable (for me at least )
Scenario
motion sensor is triggered : light is fading really slow from 0% to 100%
for any reason, I want to switch the light off while the “motion-fading” is still running
the result is the light going up (motion automation is still running) and down (switch automation is also running now) and never going neither to 100% or off as the 2 parallel script executions will end their respective “loops” at some point (worst case being that the script uses the target brightness as a stop condition to the loop, meaning it will never stop )
This is why I used the input_boolean as an optional script parameter, as this allowed me to prevent any parallel executions of the script for one specific light, while allowing parallel executions for different lights.
Still, there are probably other solutions out there that I didnt think of