How can i make automations with transition while the device doesnt support it?

Just to add, it probably wouldn’t be that hard to write something that can handle a brightness and warmth transition. Just use the repeat and delay actions to make a for loop, calling the light service every loop.

Here’s the script I mentioned. Full credit goes to mrsnyds who developed the original version; I simply consolidated his version into a single script and streamlined the code. You’ll see that the calculations to determine the optimal refresh interval and incremental brightness change take several lines of code.

However, if someone knows of a way to simplify it even further, and add color_temperature, then it would be a great contribution.

2 Likes

Oh, wow, that is definitely more foolproof than I imagined. When I said “not that hard”, I was thinking of a much more specific script, but this is certainly better.

Here’s an idea for how to add warmth, but I don’t have a use-case for this so it is untested:

Field Additions
fields:
  start_mireds:
    description: The starting warmth for the light, in mireds. The minimum is light-specific and can be found in the light state.
    example: 155
  end_mireds:
    description: The ending warmth for the light, in mireds. The maximum is light-specific and can be found in the light state.
    example: 500
`Calculate` Variable Updates
transition_secs: >-
{% set b = state_attr(light, 'brightness') %}
{% set start_level_pct = 0 if b == none else (b/255*100)|round %}                  
{% set end_level_pct = end_level_pct|int %} 
{% set t = transition.split(':') | map('int') | list %}
{{ t[0]*3600 + t[1]*60 + t[2] }}
delay_milli_sec: >-
{% set delay_milli_sec = (((transition_secs/(end_level_pct - start_level_pct))|abs)|round(precision=3)*1000)|int %}
{{ 100 if delay_milli_sec <= 99 else delay_milli_sec }}
warmth_step: >-
# This one might be able to be less sloppy,
# just trying to divide the the mired difference by the number of projected steps
{% if start_mireds and end_mireds %}
  {{ (end_mireds - start_mireds) / (transition_secs / (delay_milli_secs / 1000)) }}
`Execute_Fade` Sequence Updates
- service: light.turn_on
  data_template:
    entity_id: "{{ light }} "
    brightness_pct: >-
      {% set x = start_level_pct|int + (repeat.index|int * step_pct|int) %}
        {{ ([0, x, 100]|sort)[1] }}
    # Unsure of the behavior of this if the warmth value is undefined, this may need some adjustment
    color_temp: >-
      {% if warmth_step %}
        {{ start_mireds + (warmth_step * (repeat.index - 1)) }}
1 Like

Thanks you so much! that sounds like what i need. To be honest i find it a bit difficult to add this script to HA. I cant paste it into scripts. It doesnt allow any of that code. When i manualy try to add it to scripts.yaml it doesnt create a new service. Basicaly i have no clue what im doing./… sorry :frowning:

Can you help me how to set up your script in HA?

The script I created, based on mrsnyds work, is over a year old and doesn’t take advantage of subsequent scripting enhancements. I plan to re-write it. You can be the first tester … :slightly_smiling_face:

Here’s an updated version of the Light Fader script. It’s substantially more compact than the previous version and incorporates the latest scripting features (including the need to provide default values for various filters). It also provides a more modern UI when it’s used in Developer Tools > Services.

My testing was limited to brightening/dimming a light (both worked properly) and cancelling the fading process by manually controlling the light. None of the tests produced errors or warnings in Logs. Now it’s your turn to put it through a more grueling battery of tests.

Copy-paste the following script code to your scripts.yaml file.

Show script code
  light_fader:
    description: 'Fades lights to a desired level over a specified transition period.'
    fields:
      light:
        name: Light
        description: Entity_id of light.
        selector:
          entity:
            domain: light
        example: light.kitchen
      end_pct:
        name: End brightness Level
        description: Integer value from 0 to 100 representing the desired final brightness level.
        selector:
          number:
            min: 0
            max: 100
            step: 1
            mode: slider
        default: 50
        example: 80
      transition:
        name: Transition Time
        description: Transition time for fading indicated in HH:MM:SS format (Hours:Minutes:Seconds).
        selector:
          time:
        default: '00:10:00'
        example: '00:05:30'
    mode: parallel
    sequence:
    - variables:
        start_pct: "{{ ((state_attr(light, 'brightness') | int(0))/255*100) | round(0, default=0) }}"
        end_pct: "{{ end_pct | int(0) }}"
        delay_msec: >- 
          {% set t = strptime(transition, '%H:%M:%S').time() %}
          {{ ([100, ((((t.hour*3600 + t.minute*60 + t.second) / (end_pct - start_pct)) | abs) | round(3, default=0) * 1000) | int(0)]|sort)[1] }}
        sign: "{{ 1 if start_pct < end_pct else -1 }}"
    - repeat:
        while:
        - condition: template
          value_template: >-
            {% set b = state_attr(light, 'brightness') %}
            {% set b = (b/255*100)|round(0, default=0) if b != none else b %}
            {{  repeat.index <= 102 and
                ( (sign ==  1 and (b == none or b < end_pct)) or
                  (sign == -1 and (b != none or b|int(0) > end_pct)) ) and 
                (b | round(0, default=0) == start_pct + ((repeat.index - 1) * sign)) }}
        sequence:
        - service: light.turn_on
          target:
            entity_id: "{{ light }}"
          data:
            brightness_pct: "{{ ([0, (start_pct + (repeat.index * sign)), 100]|sort)[1] }}"
        - delay: 
            milliseconds: "{{ delay_msec }}"
4 Likes

Thanks dude! your awesome!

I can confirm it works (mostly) but there are a few problems.

  • It doenst alway reach full brightness (zigbee2mqtt debug log stops at a random point)
  • often this is after its first brightness step.
  • If i try to switch it off during the transition using a zigbee switch and a HA automation, it doest always work. usualy i have to press 2-3 times.

I’m not sure what is causing this. I may need to do some more testing, but i can see it just stops after a random number of steps. Hopefully i have more time to test soon.

Looking at your script, i dont see any possibility to set a start brightness or color temperature but i guess i can try to add these (i just have no idea where to start :nerd_face:)

Possibly due to flooding the Zigbee network with a stream of commands.

In order to produce a fairly smooth transition effect, the script must send many incremental brightness changes. Depending on the chosen transition time, it can send a command every second (or faster). In fact, the script is able to send them as quickly as every 100 milliseconds. Clearly, this can produce a lot of traffic (and can double as a ‘stress test’).

I tested it with a UPB light switch. This technology works be sending signals through the powerline. In theory, its latency is greater than Zigbee (i.e. Zigbee is faster) however I succeeded in testing it with a ~660 ms interval.

Yes, getting the light’s attention manually can be a bit tricky because it’s busy receiving (and acknowledging) all the commands sent by the script.

tl;dr
Buy a light bulb that supports transition natively. :slightly_smiling_face:

I didn’t add that functionality and, based on your light bulb’s poor performance with this script, I won’t be investing any time doing that.

1 Like

Again thank you so much for your reply and all your support! Sorry for my late reply, i have been a little busy lately.

I’m guessing you are right with flooding the Zigbee network and maybe even my other devices. I was testing at very short times between 10 and 60 seconds. If there are 256 levels of brightness thats way to many messages per second. Its actually pointless too because you will never notice that many levels of brightness.

Ideally such a script would limit the amount of messages to (for example) 1 per second. If i want to go from step 100 tot step 200 in a period of 10 seconds, it should be limited to 10 steps of 10. or at 50 seconds, 50 steps of 2. I guess this should be possible but i just not that good with programming to do it myself, but i can try :slight_smile:

I agree i could purchase a lamp that supports transitions. I might send my Lidl lamps bank and buy IKEA ones. No issue with that, and maybe the IKEA lamps are better anyway. I have to test more…

However, that does not solve all my issues. I would like such a script to support a transition of color temperature too, and i want it to start at a certain value. This is something that does not seems to be supported by any zigbee lamps. I guess a script could do this.

If you can help out with code, that would be highly appreciated. If not, thanks anyway! You really helped me a lot already. I can try on my own, but i dont really understand much about coding. If i will find a way i will surely post it here!

Hi there

first of all many thanks for the script! actually I do have a dimmer which supports transition but the effect is not as good as with your script ;). I still do have some inputs/questions that I would like to place.


It seems that the script increases the brightness in one-percent steps.
question: is it possible to increase the steps in integer-steps 0-255? for example from 0% to 10% would be 0 to 25 in steps of 1.

I found these attributes in the script-section. brightness value is in percent, brightness in integer.


Why am I asking this? The dimming-process basically looks good but the brightness-increase is noticeable and it doesnt look that natural.

Disclaimer: I dont have much coding-experience, so I might dont use the right technical wording but I hope I can express it the right way. Maybe I am also wrong and it already increases the brightness in integer-steps.

I would be happy to test the script and give feedback.

best regards

Andrew

love it!
works perfect for my needs…
use esp32 and grow light led…. with PMW …
only a small issue that i‘ll had to put „“ in the code
used before a python script that failed sometimes …
this is way better now…
thx … no issues
M.

I can’t for the life of me figure out what I’m doing wrong with this script, but I’ve just been experimenting with it on the services tab of developer tools and I can’t seem to get it to do anything. I’m not getting any errors or anything, but when I’ve tried fading my Hue lights or Meross dimmer, nothing happens whatsoever. I’ve tried fading from 0-100, 100-0, and everything in between; I just can’t seem to get it to work.

Any ideas where I could be going wrong? As I said, I’m not getting any errors.

EDIT: One thing I’ve noticed is that when I’m using the UI editor it shows the transition time as a (clock) time, with AM/PM as options. This isn’t what’s shown on your example screenshot.

1 Like

I have the same issue as @pmcenaney. Got the script, inserted into automation, but can’t seem to get it to work possibly due to HA seeing the transition time as an actual time with AM/PM values.

I noticed that hh:mm:ss when I changed to the new version of the script.

Here’s my setup with the new version. This is in yaml at the script level in a script/automation. Meaning not from the developer tools UI is where this would be used or in the developer tools switch to yaml and you can test this there too.

light: morning_lights
end_pct: 100
transition: '00:00:10'

Hey @Danny2100. I think I tried that. HA still doesn’t seem to run the transition properly. Does the script, transition, and automation work for you?

It does. Show your yaml? What kind of bulb is It?
Z-Wave or zigbee?

Maybe that’s my problem. It’s a Belkin Wemo dimmer that I’m trying to transition/fade and not the bulbs themselves. I’ll add the yaml below.

alias: 1_TEST_FADE
description: ''
trigger:
  - platform: time
    at: '10:00:00'
condition: []
action:
  - service: script.1642865980914
    data:
      light: light.dining_room_light
      end_pct: 100
      transition: '00:00:10'
mode: single

That might be the issue. Taras said above it was tested with a UPB light switch which isn’t a bulb and it worked. I’m not an expert but what are the attributes of the switch, do you see errors when attempting to run the script, how do you control this dimmer?

You can also try to send a message to taras.

Thanks @pmcenaney, it worked for my dimmers after several changes.
I changed the transition field into an integer with unit seconds, instead of “HH:MM:SS”.
And I used the repeat.index for the while loop in a simpler way.

fade_light:
  description: "Fades lights to a desired level over a specified transition period."
  fields:
    light:
      name: Light
      description: Entity_id of light.
      selector:
        entity:
          domain: light
      example: light.kitchen
    end_pct:
      name: End brightness Level
      description: Integer value from 0 to 100 representing the desired final brightness level.
      selector:
        number:
          min: 0
          max: 100
          step: 1
          mode: slider
      default: 50
      example: "50"
    transition:
      name: Transition Time
      description: Transition time for fading in seconds.
      selector:
        number:
          min: 0
          max: 1800
          step: 1
          mode: slider
      default: 10
      example: "10"
  mode: parallel
  sequence:
    - variables:
        start_pct: "{{ ((state_attr(light, 'brightness') | int(0))/255*100) | round(0, default=0) }}"
        end_pct: "{{ end_pct | int(0) | round(0, default=0) }}"
        delay_msec: >-
          {{ ([100, (((transition / (end_pct - start_pct)) | abs) | round(3, default=0) * 1000) | int(0)]|sort)[1] }}
        sign: "{{ 1 if start_pct < end_pct else -1 }}"
        n: "{{ 1000 * transition / delay_msec | int(0) }}"
    - repeat:
        while:
          - condition: template
            value_template: >-
              {{  repeat.index <= n }}
        sequence:
          - delay:
              milliseconds: "{{ delay_msec }}"
          - service: light.turn_on
            target:
              entity_id: "{{ light }}"
            data:
              brightness_pct: "{{ ([0, (start_pct + (repeat.index * sign)), 100]|sort)[1] }}"

The script sends a light.turn_on command with a new brightness level every delay_msec milliseconds. The minimum delay is st to 100, but I worry a bit if such small delay works well, because then the controller sends 10 commands per second. Maybe increase the minimum delay to 500 milliseconds?

For others who are watching this: this seems a good solution for applying transitions to lights or dimmers which do not support transitions.

Add the script above to scripts.yaml, assuming that your have script: !include scripts.yaml in your configuration.yaml.
Then call the script for example in the following way:

    - service: script.fade_light
      data:
        light: light.dimmer_living_room
        end_pct: 40
        transition: 10


The script above can also be used to fade out the light to a brightness level of 0. A zero level does not mean that the light is off, so after it has reached zero then you need to turn the light off. But… as a result, this will leave the light or dimmer in a state with brightness = 0. So, if you next turn on the light again, it will turn on with a brightness level of 0! This problem has been mentioned in other discussions.

A solution which is not great but works good enough for me is to remember the original brightness level, and quickly set that original brightness before turning the light off. This is done in the following script fade_out_light which uses the above script fade_light:

#########################
# Fade out light
fade_out_light:
  description: "Fades out lights, and remember the initial brightness."
  fields:
    light:
      name: Light
      description: Entity_id of light.
      selector:
        entity:
          domain: light
      example: light.kitchen
    transition:
      name: Transition Time
      description: Transition time for fading in seconds.
      selector:
        number:
          min: 0
          max: 1800
          step: 1
          mode: slider
      default: 10
      example: "10"
  mode: single
  sequence:
    - variables:
        initial_brightness: "{{ state_attr(light, 'brightness') | int(0) }}"
    - service: script.fade_light
      data:
        light: "{{ light }}"
        end_pct: 0
        transition: "{{ transition }}"
    - service: light.turn_on
      target:
        entity_id: "{{ light }}"
      data:
        brightness: "{{ initial_brightness }}"
    - service: light.turn_off
      target:
        entity_id: "{{ light }}"
2 Likes

@robert2s @pmcenaney @Danny2100 @123

We have a winner!

My wife just complimented the morning light transition. Much better than the lights slamming on in the AM.

Thank you for the Fade ON solution. I tested the Fade Off, which works, but won’t go over well in bedrooms. I can work around or figure something out.

1 Like