Light Fade In

How smooth is this fade out? I have Fade Out scripts that I use which recursively call themselves, but in some cases the dimming is a little clunky and jarring

I’m not sure how to stop a currently running script. If there isn’t something built in to hass you could probably create an input boolean, add a check to this script for the value, and end it when that value equals something.

1 Like

It’s not smooth at all as it increments/decrements the brightness value directly. Since zwave lights only have 255 levels of brightness, it’s noticeable if the transition time is short. However, if you run this over a longer period like a minute or more, then the stepping isn’t as noticeable. I also mainly use this to fade out my living lights over an hour after 10pm and I don’t really notice it fading out.

I mainly rewrote this to see if I could simplify the usage of the script. I wanted it to use the current brightness, not have to pass a delay parameter, to more closely match the arguments in the light component, and combine it into one script.

1 Like

Ok thanks! Sounds like it produces similar results. Good work!

[homeassistant.components.python_script.fade_light.py] Error executing script: can't multiply 
sequence by non-int of type 'float'
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.6/site- 
packages/homeassistant/components/python_script.py", line 166, in execute
    exec(compiled.code, restricted_globals, local)
  File "fade_light.py", line 30, in <module>
TypeError: can't multiply sequence by non-int of type 'float'

I think it’s this line you are having issues with

end_level = int(brightness) if brightness is not None else math.ceil(brightness_pct * 2.55)

It seems that if you pass any of the values in as a string then you get errors like this

Here is updated code that should account for strings

"""
https://community.home-assistant.io/t/light-fade-in/35509

automation:
- alias: Light 15min Fade to 100% starting an hour before sunset
    trigger:
    platform: sun
    event: sunset
    offset: "-01:00:00"
    action:
    - service: python_script.zwave_fade
        data:
          entity_id: light.level  # Entity ID to fade
          transition: 20  # Seconds to go from current to end brightness
          brightness: 255  # Brightness to end at
          brightness_pct: 100  # Brightness to end at as a percentage
"""

entity_id = data.get('entity_id')
brightness = data.get('brightness', None)
brightness_pct = data.get('brightness_pct', None)

if entity_id is not None and (brightness is not None or brightness_pct is not None):
    light = hass.states.get(entity_id)

    start_level = light.attributes.get('brightness', 0)
    transition = int(data.get('transition', 0))

    """ Use brightness or convert brightness_pct """
    end_level = int(brightness) if brightness is not None else math.ceil(
        float(brightness_pct) * 2.55)

    """ Calculate number of steps """
    steps = int(math.fabs((start_level - end_level)))
    fadeout = True if start_level > end_level else False

    """ Calculate the delay time """
    delay = round(transition / steps, 3)

    """ Disable delay anbd increase stepping if delay < 3/4 second """
    if (delay < .750):
        delay = 0
        steps = int(steps / 5)
        step_by = 5
    else:
        step_by = 1

    logger.info('Setting brightness of ' + str(entity_id) +
                ' from ' + str(start_level) + ' to ' + str(end_level) +
                ' steps ' + str(steps) + ' delay ' + str(delay))

    new_level = start_level
    for x in range(steps):
        current_level = light.attributes.get('brightness', 0)
        if (fadeout and current_level < new_level):
            break
        elif (not fadeout and current_level > new_level):
            break
        else:
            data = {"entity_id": entity_id, "brightness": new_level}
            hass.services.call('light', 'turn_on', data)
            if (fadeout):
                new_level = new_level - step_by
            else:
                new_level = new_level + step_by
            """ Do not sleep for 0 delay """
            if (delay > 0):
                time.sleep(delay)

""" Ensure light ends at the final state """
if (end_level > 0):
    data = {"entity_id": entity_id, "brightness": end_level}
    hass.services.call('light', 'turn_on', data)
else:
    data = {"entity_id": entity_id}
    hass.services.call('light', 'turn_off', data)
1 Like

Thanks for the fix but it’s behaving unusually. The transition parameter seems to be ignored. The lights are being hit real fast so some of them drop off. This is breaking the script completely.

[homeassistant.components.light.xiaomi_miio] Setting brightness failed: Unable to discover the device 192.168.31.24

I’m testing using the service from HASS UI

I only tested this with zwave dimmer switches and used it to fade over minutes not seconds. The fastest transition I was able to get was around 10 seconds, but it was choppy and sometimes didn’t work. I do have some Hue lights but those already support the transition parameter for light.turn_on so I don’t use this script for them. I have no idea how this script would act on bulbs using other protocols.

Tanx for a great script I love it. the transition works great, but I’m currently using in a alarmclock setup where I start it 30 min before the actual alarm, but I’m strugling to stop the script, if e.g I forgot to turn of the alarm.
I think a way to do that would be to introduse a new ‘elif’ to break the ‘for’ loop?
How would I do that by using a bolean input?

       new_level = start_level
    for x in range(steps):
        current_level = light.attributes.get('brightness', 0)
        cancel = hass.states.get('input_boolean.alarm_clock_status')
        if (fadeout and current_level < new_level):
            break
        elif (not fadeout and current_level > new_level):
            break
        elif (cancel == 'off'):
            break
        else:
            data = {"entity_id": entity_id, "brightness": new_level}
            hass.services.call('light', 'turn_on', data)
            if (fadeout):
                new_level = new_level - step_by
            else:
                new_level = new_level + step_by
            """ Do not sleep for 0 delay """
            if (delay > 0):
                time.sleep(delay)

I have tried something like this but I cant seem to make it work…

Finaly made it work with this:

new_level = start_level
while new_level < end_level:
current_level = light.attributes.get('brightness', 0)
if (hass.states.get("input_boolean.alarm_clock_status").state == "off"):
    break
elif (fadeout and current_level < new_level):
    break
elif (not fadeout and current_level > new_level):
    break
else:
    data = {"entity_id": entity_id, "brightness": new_level}
    hass.services.call('light', 'turn_on', data)
    if (fadeout):
        new_level = new_level - step_by
    else:
        new_level = new_level + step_by
    """ Do not sleep for 0 delay """
    if (delay > 0):
        time.sleep(delay)

""" Ensure light ends at the final state """
if  (hass.states.get("input_boolean.alarm_clock_status").state == "off"):
data = {"entity_id": entity_id}
hass.services.call('light', 'turn_off', data)
logger.info('fadein canceled')
elif (end_level > 0):
data = {"entity_id": entity_id, "brightness": end_level}
hass.services.call('light', 'turn_on', data)
logger.info('fadein finished')
else:
data = {"entity_id": entity_id}
hass.services.call('light', 'turn_off', data)

Where the input.bolean is the on/off of the alarclock

2 Likes

Could we increase default step from 1 to 3 and from 5 to 10? How would the code change for that

Ideally the stepping would change based on the transition time and not an arbitrary value (1 or 5).
I think even a step delay of .75 sec is too quick and should probably only run once per second.
Once I get a moment to do some math I will rewrite this so the stepping is more dynamic.

1 Like

Also, to actually answer your question, it would be this section

""" Calculate number of steps """
steps = int(math.fabs((start_level - end_level)))
fadeout = True if start_level > end_level else False

""" Calculate the delay time """
delay = round(transition / steps, 3)

""" Disable delay and increase stepping if delay < 3/4 second """
if (delay < .750):
    delay = 0
    steps = int(steps / 5)
    step_by = 5
else:
    step_by = 1

You would change step_by and delay to account for the transition time.

I would go more conservative and do it once per 2 seconds. I use group lights (sometimes 5 in 1) that are slower to update.

I tried tinkering with the numbers but got errors (-ve brightness values).

I found the solution from this topic quite misleading (at least for me; I had to spent quite some time debugging the script from the topic head), because for simple scenario a simple automation with transition parameter will do

e.g. timer-triggered automation:

  • alias: “Alarm timer action”
    id: ‘timer_action’
    trigger:
    • platform: event
      event_type: timer.finished
      event_data:
      entity_id: timer.alarm_clock
      action:
    • service: light.turn_on
      data:
      entity_id: light.mylight
      brightness: 1
      kelvin: 4000
      transition: 1
    • service: light.turn_on
      data:
      entity_id: light.mylight
      brightness: 200
      kelvin: 4000
      transition: 600

Be interested in someone with experience/detail in this area chiming in.
In the light docs it says, “Most lights do not support all attributes”. Indeed it seems that my Insteon AND my Z-Wave dimmers do not support the transition attribute.

Either that or I’m doing something wrong. Since my lights seem to transition at the same rate/speed no matter what I set that to or not.

Would LOVE to know a bit more detail as to the options here.

Thanks @zanixmechanix. This worked perfectly for fading my Leviton Dimmer switch on and off. When I realized “transition” would not work on these switches I started to search on other ways. It took a while to come across this thread, but relieved I did. Hopefully this gets added in to Home Assistant.

Did you ever make a determination on this for Insteon dimmers?

Indeed it seems that my Insteon AND my Z-Wave dimmers do not support the transition attribute.

Hi
This script work fine for me.
But I have a one question.

How can I stop the script once started? On some occasion I may not want to wait for it to end

Thanks

I guess you insert a check in the script, on every occurence check if the light has been set off or unavailable, then exit the loop accordingly

Hi.

Script works great for dimming my zigbee lights.

How would i proceed for adding dimming of multiple lights at the same time? Can the script be run in parallell, or do i need more input to the python script?