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 }}"