Hello! I’m really interested on this feature, do you ahve any update on this since then?
Im still working on it.
Because I’m using absolute values opposed to percentages, I have to implement it for every type of lamp differently. I’m testing if the fading is smooth enough when using the percentages. Check back in a few weeks.
Kinds regards,
Ingrid
Great script!
Why does the script turn off the light completely when setting the brightness_end to 1? I have to set it to 2 to dim lowest light without turning lamp off.
Feature for future: Would it be possible to add a curve that is more like a sinus or similar, that is slow also at the end and not only in the beginning of the dimming?
Hi Thomas,
The turn off with endpoint 1 is a bug thanks for the feedback, I will look into this.
The sinus would be a good addition, maybe the easiest way to address this is to consider it two opposite exp5 formula’s…
New version is coming this weekend.
Kind regards Ingrid
@studioIngrid Just to check, does the above caveat mean that when the light is off, one has to define both brightness_start
and brightness_end
for the fade to be able to take place?
For instance, if the light were to be off and if I were to call this script while omitting brightness_start
but with brightness_end
being set to (say) 20
, would that do nothing?
PS Just as a very minor thing—it looks like there’s an eensy typo in that caveat (“brighness_start” and “brighness_end” rather than “brightness_start” and “brightness_end”).
Got this working yesterday but with a small caveat.
If I use fade in and the light is off, light will turn on at the latest level it was, then go back down to 0 as I want it. After that fade it works normally.
I tried commenting this part out and editing it like so:
# GET CURRENT STATE
states = hass.states.get (entity_id)
#b_cur = b_initial = states.attributes.get ('brightness') or 0
b_cur = b_initial = 0
t_cur = t_initial = states.attributes.get ('color_temp') or 0
But the effect remains.
Great script otherwise!
For me the fade in tests starts with whatever I have set brightness_start to be which is one.
What I am noticing for the fade out tests is that the light physical will turn off completely at the end of the duration, but in HA the light shows still on at a brightness of 1.
update: I may just take it back of what I said about about the fade out issue. I was testing with duration of 1 minute and less. I tried with 3 minute duration and HA shows turn off now.
I created a services.yaml for this script to use the UI selectors.
It would be nice to make color_temp optional as some dimmable lamps don’t have this feature.
#<config>/python_scripts/services.yaml
smooth_fader:
name: Smooth Fader
fields:
entity_id:
# entity_id: light.entity ; required
description: The light that will be turned on.
example: light.myDimmer
required: true
selector:
entity:
include_entities:
- light.myDimmer
duration:
# duration: '00:00:00' ; required, time under 10 seconds is not advised
description: Duration Time, Time under 10 seconds is not advised.
example: "00:00:10"
default: "00:00:10"
required: true
selector:
time:
brightness_start:
# brightness_start: 0-255 ; default: current
description: Start brightness.
example: 0
default: 0
selector:
number:
min: 0
max: 255
brightness_end:
# brightness_end: 0-255 ; default: current
description: End brightness.
example: 255
default: 255
selector:
number:
min: 0
max: 255
brightness_curve:
# brightness_curve: 'linear' or 'exp2' or 'exp5' or 'smooth' ; default: exp5
description: Light brightness curve algorithm
example: exp5
default: exp5
selector:
select:
options:
- linear
- exp2
- exp5
- smooth
temperature_start:
# temperature_start: 154-370 ; default: current
description: Start temperature
example: 154
default: 154
selector:
number:
min: 154
max: 370
temperature_end:
# temperature_end: 154-370 ; default: current
description: End temperature
example: 154
default: 154
selector:
number:
min: 154
max: 370
temperature_curve:
# temperature_curve: 'linear' or 'exp2' or 'exp5' or 'smooth' ; default: exp2
description: Light temperature curve algorithm
example: exp2
default: exp2
selector:
select:
options:
- linear
- exp2
- exp5
- smooth
Hi MiniCooper246, could you explain to me how i can use your script? I am interested, Thank you!
nice script, thank you! Would it be a lot of work to add color to it? Say for a sunrise simulation?
The Python Script itself is not made by me, only the services.yaml.
A service.yaml is a declaration File to use the script more easily from the HomeAssistant Web UI.
(service.yaml Docs)
But you have to edit it slightly in this area. it requires a list of light entities you want to be able to control.
selector:
entity:
include_entities:
- light.myDimmer
Color is supported by default (i think) but i could not test it, because my lights don’t have a color feature. So I had to edit the original Script slightly to not bug, because it can’t access the color temp of my lights.
Hi Community !
First of all, thank you very much for this script. Im trying to find some complex solution veeeeeeery long time ago, and this is so far the most stable and “smooth” option.
Can you please support me with 2details in this script ?
-
I would like to achieve dimming/fading UP or DOWN for my lights from "current state-so current brightness, temperature, colour)
However, if i try to run the script WITH defined END BRIGHTNESS, without temperature values, the script throws an error that temperature should be defined. How can i please avoid this, and control only the BRIGHTNESS part (of course with duration and curve) ? With mono lights/strips is not such a big deal (however im using different temperatures during the day) but with RBG is that even worse. -
Sometimes would be great to stop the script from further execution, if light is turned off or brightness changed manually during script running. Is is please possible somehow ?
I can test nearly immediate any change, if needed.
Thank you very much !
Hi all, I am currently updating the script. Working on these changes:
- add rgb color support
- breakout for animations duration > 10 sec
- breakout service to stop all animations
- wrap in custom integration to call async
Will post when update is ready.
— Ingrid
Hi @studioIngrid !
Sounds great ! Can i help you with testing maybe to make the changes quicker ?
About the first part i mention, to “start dimming up or down” without brightness start defined, could be some achievements possible please ?
Thank you !
Greetings
Ronnie
@studioIngrid If I might make a request for the script update, might it be possible for the script to detect whether the target lights support changes in color temperature, and if not, to have it omit those commands?
I ask just since I have some Lutron lights that support brightness (but not color temperature), and at the moment, the script doesn’t seem to work for those lights.
(On the other hand, the script works fabulously for my Hue bulbs—which support both brightness and color temperature—so I can confirm that I’ve got the script installed properly, as best as I can tell.)
Great idea, as I plan to also include RGB color change, so I will be sure to include this.
Thank you so much for this great script! I’m looking forward to the further improvements you’ve indicated in earlier posts, particularly breaking off if a manual change is detected, and rgb support. Are you planning to add xy_color support as part of rgb?
Thanks @studioIngrid, I’ve not tried your code, but it appears to be exactly what I’m after.
CAVEAT: I’m not a programmer
I may be able to chip in on the colour convesion issue that I want to resolve for another use case. The code below is more of an FYI as I can use your code as is, and noting my caveat, It would take me months to integrate it into yours.
To give context to the code, here’s the sequence of how it came about:
- I have RGBW lights that can supports many of the variations of color definitions and color temperature
- I found the Adaptive Lighting integration
- I stopped using the integration because as it turns out, my fully capable RGBW lights would only go to a max mireds of 370 and the light colours when using RGB mode in adaptive lighting didn’t look correct
- I then realised I could do my own colour conversion and use it in automations for my lights that uses the Adaptive Lighting colour temp and brightness profiles, but with my version of the colour conversion
- I found this wikipedia page for an approximation of colour temp in the xy colour space, which I used in a template successfully
- For various reasons, I wanted it to make it overly complicated and frustrating, so I turned to python and colour science
- I hit a various home assistant lockdowns and walls, and ended up having to take the conversion code from the colour science library (many types of conversions).
- I couldn’t get the key component (conversion of colour temp to xy) to work so I mash the colour science code together with the approximation I have above
With that said, this is the gist of how the various code blocks below work:
- The Adaptive Lighting integration must be installed and when configuring in the UI, this checkbox must be checked: include_config_in_attributes
- Template sensors are used to store the colour temp from adaptive lighting as the value and the colour conversions as attributes, but start with placeholders for the values
- When adaptive lighting causes a change to the template sensor value, a generic automation calls the AppDaemon python code for the conversion
- The App then updates the template sensors’ attributes
Note:
- This code will throw errors on startup if you try to turn on lights prior to there being a change in the adpative lighting attributes
- Adaptive lighting isn’t actually required if all you want is the conversion of the colour temp, you’ll just have to change the automation to suit, or take the maths out of the python code and put it in a template sensor
- If you’re starting with Kelvin, to convert to mireds:
mireds = 1,000,000 / Kelvin
I’m happy to answer any questions, but I don’t spend much time on this forum, so my answers will likely be delayed.
Template sensor example (the old school template sensor format is below):
- platform: template
sensors:
adaptive_lighting_mireds_bedroom:
value_template: "{{ state_attr('switch.adaptive_lighting_bedroom', 'color_temp_mired') }}"
attribute_templates:
rgb_colour: 0
hs_colour: 0
xy_colour: 0
kelvin: 0
brightness_pct: "{{ state_attr('switch.adaptive_lighting_bedroom', 'brightness_pct') }}"
Create as many template sensors as you want. The naming is important for the automation, so make sure each sensor name starts with adaptive_lighting_mireds_
and change bedroom
to the various unique identifiers of your choice.
Automation:
- alias: Update adaptive lighting mireds conversion sensors
trigger:
- platform: event
event_type: state_changed
condition:
- condition: template
value_template: '{{ trigger.event.data.entity_id.startswith("sensor.adaptive_lighting_mireds_")
}}'
action:
- choose:
- conditions:
- condition: template
value_template: '{{ is_state(trigger.event.data.entity_id, ''unknown'') }}'
sequence:
- service: persistent_notification.create
data:
title: Adaptive lighting mireds conversion sensor not found
message: The adaptive lighting mireds conversion sensor for {{ trigger.event.data.entity_id
}} could not be found. Please create it first.
default:
- event: adaptive_lighting_mireds_conversion
event_data:
entity_id: '{{ trigger.event.data.entity_id }}'
value: '{{ trigger.event.data.new_state.state }}'
Apps.yaml
AdaptiveLightingMiredsConversion:
module: adaptive_lighting_mireds_conversion
class: AdaptiveLightingMiredsConversion
AppDaemon filename: adaptive_lighting_mireds_conversion.py
in a folder of the same name
adaptive_lighting_mireds_conversion.py
import appdaemon.plugins.hass.hassapi as hass
import numpy as np
class AdaptiveLightingMiredsConversion(hass.Hass):
def initialize(self):
self.listen_event(self.trigger_conversion,
"adaptive_lighting_mireds_conversion")
def trigger_conversion(self, event_name, data, kwargs):
if 'entity_id' in data:
self.sensor_entity_id = data["entity_id"]
mireds = float(data["value"])
cct = 1e6 / mireds
rgb = self.colour_temperature_to_rgb(cct)
hs = self.rgb_to_hs(rgb)
xy = self.cct_to_xy(cct)
kelvin = self.colour_mireds_to_kelvin(cct)
self.log(f"RGB: {rgb}, HS: {hs}, xy: {xy}, kelvin: {kelvin}")
# Update the sensor value
self.set_state(self.sensor_entity_id, state=mireds,
attributes={"rgb_colour": rgb, "hs_colour": hs, "xy_colour": xy, "kelvin": kelvin})
def cct_to_xy(self, cct):
M = 1e6 / cct
if cct < 4000:
x = - 0.2661239 * 1e9 / (cct ** 3) - 0.2343580 * 1e6 / (cct ** 2) + \
0.8776956 * 1e3 / cct + 0.179910
elif cct <= 25000:
x = - 3.0258469 * 1e9 / (cct ** 3) + 2.1070379 * 1e6 / (cct ** 2) + \
0.2226347 * 1e3 / cct + 0.240390
else:
x = - 0.11026621 * (M ** 3) + 0.0516377 * (M ** 2) + \
0.075919 * M + 0.206556
if cct < 2222:
y = - 1.1063814 * (x ** 3) - 1.34811020 * \
(x ** 2) + 2.18555832 * x - 0.20219683
elif 2222 <= cct and cct < 4000:
y = - 0.9549476 * (x ** 3) - 1.37418593 * (x ** 2) + 2.09137015 * x - 0.16748867
elif 4000 <= cct and cct < 25000:
y = 3.0817580 * (x ** 3) - 5.87338670 * \
(x ** 2) + 3.75112997 * x - 0.37001483
else:
y = 1
return x, y
def xyY_to_XYZ(self, xyY):
x, y, Y = xyY
X = (Y / y) * x
Z = (Y / y) * (1 - x - y)
return X, Y, Z
def XYZ_to_sRGB(self, XYZ):
M = np.array([[3.2406, - 1.5372, - 0.4986],
[- 0.9689, 1.8758, 0.0415],
[0.0557, - 0.2040, 1.0570]])
linear_rgb = np.dot(M, XYZ)
return linear_rgb
def gamma_correct_sRGB(self, linear_rgb):
gamma_corrected_rgb = np.where(
linear_rgb <= 0.0031308,
linear_rgb * 12.92,
1.055 * (linear_rgb ** (1 / 2.4)) - 0.055)
return gamma_corrected_rgb
def colour_temperature_to_rgb(self, cct):
# Step 1: Convert colour temperature to xy chromaticity coordinates
xy = self.cct_to_xy(cct)
# Step 2: Convert xyY to XYZ (assuming Y = 1)
Y = 1.0
XYZ = self.xyY_to_XYZ((xy[0], xy[1], Y))
# Step 3: Convert XYZ to linear sRGB
linear_rgb = self.XYZ_to_sRGB(XYZ)
# Step 4: Apply gamma correction
gamma_corrected_rgb = self.gamma_correct_sRGB(linear_rgb)
# Clamp the RGB values to the [0, 1]
# range and convert them to 8 - bit integers
clamped_rgb = np.clip(gamma_corrected_rgb, 0, 1) * 255
# Convert the NumPy array to a list
return clamped_rgb.astype(int).tolist()
def rgb_to_hs(self, rgb):
r, g, b = [val / 255.0 for val in rgb]
max_value = max(r, g, b)
min_value = min(r, g, b)
difference = max_value - min_value
if max_value == min_value:
h = 0
elif max_value == r:
h = (60 * ((g - b) / difference) + 360) % 360
elif max_value == g:
h = (60 * ((b - r) / difference) + 120) % 360
elif max_value == b:
h = (60 * ((r - g) / difference) + 240) % 360
if max_value == 0:
s = 0
else:
s = difference / max_value
return h, s * 100
def colour_mireds_to_kelvin(self, cct):
return cct
Hi, sorry for ressucitate this topic, but I got a problem with my light.
I have a single WIFI dimmer that I want to turn it on and off from 0 to 60% in 30 minutes.
It is not RGB.
I installed this script, but when I run, I get this error about color_temp. How can I workarround ?
ERROR (SyncWorker_19) [homeassistant.components.python_script.smooth_fader.py] Error executing script: value must be at least 1 for dictionary value @ data['color_temp']
File "/usr/src/homeassistant/homeassistant/components/python_script/__init__.py", line 224, in execute
File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 451, in result
File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 232, in __call__
File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 355, in _exec
File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 351, in _exec
File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 272, in __call__
File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 272, in __call__
File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 229, in _run
File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 355, in _exec
File "/usr/local/lib/python3.10/site-packages/voluptuous/validators.py", line 353, in _exec
File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 818, in validate_callable
File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 272, in __call__
File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 595, in validate_dict
File "/usr/local/lib/python3.10/site-packages/voluptuous/schema_builder.py", line 433, in validate_mapping
Running with the code :
service: python_script.smooth_fader
data:
entity_id: light.controller_dimmable_b6af10
brightness_curve: linear
brightness_start: 0
brightness_end: 120
duration: "00:00:30"```
Hi,
I haven’t worked on this code for a while. And I’m currently busy with other projects.
Did you check out Ashley’s script? Here.
I didn’t test is yet, but looks like it might be what you need.
— Ingrid