Light Fade In

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?

Hi everyone I know I am a year late to the party but I have used this script as a starting point for a fadeout using appdaemon in HomeAssistant and have come across a strange issue where it does not appear as though the brightness is getting updated correctly through every step. The dimming portion of my code is below:

        while new_level > end_level: 
            self.call_service("light/turn_on", entity_id = "light.switchlight_livingroom", brightness = new_level)
            time.sleep(delay)
            brightness_compare = self.get_state("light.switchlight_livingroom", attribute = "brightness")
            self.log("step count: %s", step_count)
            self.log("new level: %s", new_level)
            self.log("brightness %s", brightness_compare)
            step_count = step_count +1
            new_level = math.ceil(new_level - step)

I am trying to put a break into this by comparing the current brightness level and the expected brightness level and my thought is that if the brightness is increased or decreased by more than expected the script would stop via a break. I figure this way some one could stop the automation by simply holding up or down for a couple of seconds on the physical switch and not have to interact with the dashboard. The problem however is when comparing the log outputs of new_level and brightness_compare they do not always line up. Below is an output of the log showing this issue:

2021-10-28 09:45:27.932990 INFO sleep: turning on the light to 31.0
2021-10-28 09:45:35.602806 INFO sleep: step count: 1
2021-10-28 09:45:35.609848 INFO sleep: new level: 80
2021-10-28 09:45:35.613089 INFO sleep: brightness 80
2021-10-28 09:45:43.199813 INFO sleep: step count: 2
2021-10-28 09:45:43.206852 INFO sleep: new level: 79
2021-10-28 09:45:43.210961 INFO sleep: brightness 80
2021-10-28 09:45:50.798141 INFO sleep: step count: 3
2021-10-28 09:45:50.804222 INFO sleep: new level: 78
2021-10-28 09:45:50.808597 INFO sleep: brightness 77
2021-10-28 09:45:58.392228 INFO sleep: step count: 4
2021-10-28 09:45:58.400281 INFO sleep: new level: 77
2021-10-28 09:45:58.403340 INFO sleep: brightness 77
2021-10-28 09:46:05.989883 INFO sleep: step count: 5
2021-10-28 09:46:05.995038 INFO sleep: new level: 76
2021-10-28 09:46:05.998829 INFO sleep: brightness 77
2021-10-28 09:46:13.580121 INFO sleep: step count: 6
2021-10-28 09:46:13.589430 INFO sleep: new level: 75
2021-10-28 09:46:13.592049 INFO sleep: brightness 75
2021-10-28 09:46:21.184359 INFO sleep: step count: 7
2021-10-28 09:46:21.188516 INFO sleep: new level: 74
2021-10-28 09:46:21.192664 INFO sleep: brightness 75
2021-10-28 09:46:28.791374 INFO sleep: step count: 8
2021-10-28 09:46:28.795228 INFO sleep: new level: 73
2021-10-28 09:46:28.798479 INFO sleep: brightness 72
2021-10-28 09:46:36.385752 INFO sleep: step count: 9
2021-10-28 09:46:36.389869 INFO sleep: new level: 72
2021-10-28 09:46:36.395894 INFO sleep: brightness 72
2021-10-28 09:46:43.980320 INFO sleep: step count: 10
2021-10-28 09:46:43.988076 INFO sleep: new level: 71
2021-10-28 09:46:43.991320 INFO sleep: brightness 72

What is really odd is that no matter what I make the starting brightness, duration, or step, the disconnect between the brightness_compare and new_level always happen on the exact same numbers ie: new_level: 74 / brightness_compare: 75.

Has anyone else experienced this before and if so, do you have any solutions? I am using GE Jasco 14294 smart dimmer switches if that helps.

Pardon me for resurrecting this but I’ve been trying to use transitions and my hardware does not support it.

I’ve been trying to find documentation to no avail. How do I include/implement/install this script in my installation? Where does the python script go? How do I call upon it?

Look at the python script integration

This is my version of a generic light fader script here. It’s also based on Python but avoids calling the dreaded time.sleep() function. This implementation uses time calculations to determine what the current value should be at any point. And rate limiting is handled with both step size and maximum number of api calls per second. The script is also fully reversible! So it can be used for fading in and out!

I hope this will help out other people trying to build light alarms (my use case) ;D

entity_id = data.get('entity_id')
transition_time = int(data.get('transition'))
brightness_pct = int(data.get('brightness'))

# Hard coded values
MIN_TIME_BETWEEN_CALLS = 0.5
MIN_STEP_SIZE = 1
MAX_BRIGHTNESS_DEVIATION = 3

# Helper functions
def calc_delta(new_value, old_value):
    return abs(abs(new_value) - abs(old_value))

# Absolute values used in calculations for API-Calls
initial_brightness = int(hass.states.get(entity_id).attributes.get('brightness') or 0)
final_brightness = int(255 * brightness_pct / 100)

# Time Setup
start_time = time.time()
end_time = start_time + transition_time
transition_range = final_brightness - initial_brightness

# Variable used for rate limiting
previous_passed_time = 0
previous_step_over_start = 0

# Variables used to determine user triggered stop
previous_level = initial_brightness
user_changed_brightness = False

# Transition loop
while end_time > time.time():
    # Calculate current brightness based on current time
    passed_time = transition_time - (end_time - time.time())
    progress_ratio = passed_time / transition_time

    step_over_start = transition_range * progress_ratio
    new_level = int(initial_brightness + step_over_start)

    # This check makes sure the light bulb cannot be called more than twice per second and the individual increases need to be the size of at least 1
    if calc_delta(passed_time, previous_passed_time) > MIN_TIME_BETWEEN_CALLS and \
       calc_delta(step_over_start, previous_step_over_start) > MIN_STEP_SIZE:
        # This check causes the transition to stop if the brightness was changed by another script/user
        # I put it in here to avoid quering the current value of the light too many times
        actual_brightness = int(hass.states.get(entity_id).attributes.get('brightness') or 0)
        if calc_delta(actual_brightness, previous_level) < MAX_BRIGHTNESS_DEVIATION and \
           calc_delta(previous_level, actual_brightness) < MAX_BRIGHTNESS_DEVIATION:
            data = {"entity_id": entity_id, 'brightness': new_level}
            hass.services.call('light', 'turn_on', data)
            previous_passed_time = passed_time
            previous_step_over_start = step_over_start
            previous_level = new_level
        else:
            user_changed_brightness = True
            break

# Set to light to end terminal brightness
if not user_changed_brightness:
    data = {"entity_id": entity_id, 'brightness': final_brightness}
    hass.services.call('light', 'turn_on', data)
# services.yaml
lightfader:
  description: Turn on a light with a generic transition for entities that don't have support for it
  fields:
    entity_id:
      description: The light or group that will be turned on.
      example: light.video_light
    transition:
      description: The amount of seconds the transition should take
      example: 10
    brightness:
      description: desired brightness in %
      example: 100
3 Likes

I followed the documentation for python scripts as best as I could and copy/pasted your python code into a file named “lightfader” within the python_scripts folder. I made the services.yaml file and copy/pasted that part also. Is this correct? Or are there things within the code that need changing to suit my use?

If I got that part right, how do I use this in an automation?

I tried the following among a few variations but I don’t think I’m on the right track…

  alias: New Automation
  description: ''
  trigger:
  - device_id: 1fa4ae801eecc32b6db7b57a26040126
    domain: zha
    platform: device
    type: remote_button_short_press
    subtype: remote_button_short_press
  condition: []
  action:
  - service: python_script.lightfader
    target:
      entity_id: light.lounge_lights
    data:
      transition_time: 20
      brightness_pct: 100
  mode: single

Seems like you try to call it with the wrong variable names. I call the script like so:

- service: python_script.lightfader
  data: 
    entity_id: light.bedroom_lights
    transition: 20
    brightness: 100