The following is a fragment from one of my automations for controlling a light’s brightness via a remote-control.
If the button event is either brightness_move_down or brightness_move_up, it calculates the following variables:
brightness_from: The light's current brightness level.
brightness_target: The target brightness; 5 if dimming, 255 if brightening.
brightness_delta: The difference between the light's current brightness and the target brightness.
transition_time: The time it will take to dim/brighten from the current brightness to the target brightness. Uses a predetermined fade speed.
fade_speed: If dimming then make the fade speed a negative value.
Then it simply uses light.turn_on and sets transition and brightness. So if the light is currently at 20% and the user presses and holds the ‘brighten’ button, the light begins transitioning from 20% (51) to 100% (255). The light itself performs the brightening process (due to the use of the transition option).
- variables:
fade_speed: 60
event: "{{ trigger.to_state.attributes.event_type }}"
- choose:
- conditions: "{{ event in ['brightness_move_down', 'brightness_move_up'] }}"
sequence:
- variables:
brightness_from: "{{ state_attr(light, 'brightness') | int(0)}}"
brightness_target: "{{ iif(event == 'brightness_move_down', 5, 255) }}"
brightness_delta: "{{ (brightness_from - brightness_target) | abs }}"
transition_time: "{{ brightness_delta / fade_speed }}"
fade_speed: "{{ fade_speed * iif(event == 'brightness_move_down', -1, 1) }}"
- action: light.turn_on
target:
entity_id: '{{ light }}'
data:
transition: '{{ transition_time }}'
brightness: '{{ brightness_target }}'
The final part is detecting when the user releases the ‘brighten’ button via a brightness_stop event. The automation uses a wait_for_trigger to detect the button event.
Upon detecting the event, it uses light.turn_on to set the light’s brightness level.
It computes the brightness based on how long the user pressed and held the button (the starting brightness plus the amount of time that has elapsed multiplied by the fade speed). So if the user releases the button when the light is approximately 80% brightness, the automation executes a light.turn_on command with brightness set to 204 (80%). This stops the light’s transition process (which was increasing to 100% brightness) and sets it to the user’s desired final brightness level.
- conditions: "{{ event in ['brightness_move_down', 'brightness_move_up'] }}"
sequence:
- variables:
brightness_from: "{{ state_attr(light, 'brightness') | int(0)}}"
brightness_target: "{{ iif(event == 'brightness_move_down', 5, 255) }}"
brightness_delta: "{{ (brightness_from - brightness_target) | abs }}"
transition_time: "{{ brightness_delta / fade_speed }}"
fade_speed: "{{ fade_speed * iif(event == 'brightness_move_down', -1, 1) }}"
- action: light.turn_on
target:
entity_id: '{{ light }}'
data:
transition: '{{ transition_time }}'
brightness: '{{ brightness_target }}'
- wait_for_trigger:
- trigger: state
entity_id: event.office_dimmer_action
not_from: 'unavailable'
not_to: 'unavailable'
timeout: '{{ transition_time }}'
continue_on_timeout: false
- if: "{{ wait.trigger.to_state.attributes.event_type == 'brightness_stop' }}"
then:
- action: light.turn_on
target:
entity_id: '{{ light }}'
data:
brightness: >
{{ (brightness_from + fade_speed * (wait.trigger.to_state.last_changed - trigger.to_state.last_changed).total_seconds()) | round(0) }}
I have used this technique successfully, for the past two years, for several lights. Responsiveness is satisfactory, largely because there are only two Zigbee commands involved, the first starts the automatic dimming/brightening process and the second one stops it and sets the desired brightness.