Skip to content

Instantly share code, notes, and snippets.

@Ltek
Created October 17, 2025 15:30
Show Gist options
  • Select an option

  • Save Ltek/27a83afea0a073834052bd055995da4b to your computer and use it in GitHub Desktop.

Select an option

Save Ltek/27a83afea0a073834052bd055995da4b to your computer and use it in GitHub Desktop.
Home Assistant Blueprint : Shelly i4 Button Controller by Ltek
blueprint:
name: 📛 Shelly i4 Button Controller by Ltek
description: >
Shelly i4 Button Controller by Ltek
🚀 Version 2025.10.16.01
✅ Features:
- Set any HA Action for Button presses (Single, Double, Triple, Down, Up, Long)
- Single Button Dim any or all buttons (optional)
- Dim Direction Start Boundary - sets dim direction at start of dim; upward if below, downward if above
- When Dim Function is Enabled
- if the Light is OFF, Long press turns on the Light then Dims
- Basic Actions for Button Up and Long Press are disabled
- Dim Fine Tuning - Dim % per Step and Step Interval (time delay between steps) allows for you to tune dimming as you'd like
📖 Community Discussion, Help, and Details... https://community.home-assistant.io/
source_url: https://gist.github.com/Ltek/
domain: automation
input:
shelly_device:
name: 📛 Shelly device
selector:
device:
manufacturer: Shelly
button1_basic_actions:
name: "🔘 Button 1 - Basic Actions"
description: Configure basic button press actions
collapsed: true
input:
button1_single:
name: Single Press
selector:
action: {}
default: []
button1_double:
name: Double Press
selector:
action: {}
default: []
button1_triple:
name: Triple Press
selector:
action: {}
default: []
button1_down:
name: Button Down
selector:
action: {}
default: []
button1_up:
name: Button Up
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button1_long:
name: Long Press
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button1_dim_settings:
name: "💡 Button 1 - Dimming Settings"
description: Configure dimming functionality for long press
collapsed: true
input:
button1_dim_enabled:
name: Enable Dim Function
description: When enabled the above actions for Long Press and Button Up are Disabled
selector:
boolean: {}
default: false
button1_dim_target:
name: Light Entity or Group you want to Dim
selector:
entity:
domain: light
default: ""
button1_dim_step:
name: Dim Step Percent
description: Change light Brightness this amount per dim cycle. (1 to 50)
selector:
number:
min: 1
max: 50
unit_of_measurement: '%'
default: 2
button1_dim_delay:
name: Dim Interval (seconds)
description: Time between each dim cycle. (0.05 to 2.0)
selector:
number:
min: 0.05
max: 2
unit_of_measurement: seconds
default: 0.2
button1_boundary:
name: Dim Boundary Percent
description: At Dim Start, if the light is Below this Brightness Level, the dim will Increase Brightness, otherwise it will Decreases Brightness
selector:
number:
min: 0
max: 100
unit_of_measurement: '%'
default: 50
button2_basic_actions:
name: "🔘 Button 2 - Basic Actions"
description: Configure basic button press actions
collapsed: true
input:
button2_single:
name: Single Short Press
selector:
action: {}
default: []
button2_double:
name: Double Short Press
selector:
action: {}
default: []
button2_triple:
name: Triple Short Press
selector:
action: {}
default: []
button2_down:
name: Button Down
selector:
action: {}
default: []
button2_up:
name: Button Up
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button2_long:
name: Long Press
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button2_dim_settings:
name: "💡 Button 2 - Dimming Settings"
description: Configure dimming functionality for long press
collapsed: true
input:
button2_dim_enabled:
name: Enable Dim Function
description: When enabled the above actions for Long Press and Button Up are Disabled
selector:
boolean: {}
default: false
button2_dim_target:
name: Light Entity or Group you want to Dim
selector:
entity:
domain: light
default: ""
button2_dim_step:
name: Dim Step Percent
description: Change light Brightness this amount per dim cycle. (1 to 50)
selector:
number:
min: 1
max: 50
unit_of_measurement: '%'
default: 2
button2_dim_delay:
name: Dim Interval (seconds)
description: Time between each dim cycle. (0.05 to 2.0)
selector:
number:
min: 0.05
max: 2
unit_of_measurement: seconds
default: 0.2
button2_boundary:
name: Dim Boundary Percent
description: At Dim Start, if the light is Below this Brightness Level, the dim will Increase Brightness, otherwise it will Decreases Brightness
selector:
number:
min: 0
max: 100
unit_of_measurement: '%'
default: 50
button3_basic_actions:
name: "🔘 Button 3 - Basic Actions"
description: Configure basic button press actions
collapsed: true
input:
button3_single:
name: Single Short Press
selector:
action: {}
default: []
button3_double:
name: Double Short Press
selector:
action: {}
default: []
button3_triple:
name: Triple Short Press
selector:
action: {}
default: []
button3_down:
name: Button Down
selector:
action: {}
default: []
button3_up:
name: Button Up
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button3_long:
name: Long Press
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button3_dim_settings:
name: "💡 Button 3 - Dimming Settings"
description: Configure dimming functionality for long press
collapsed: true
input:
button3_dim_enabled:
name: Enable Dim Function
description: When enabled the above actions for Long Press and Button Up are Disabled
selector:
boolean: {}
default: false
button3_dim_target:
name: Light Entity or Group you want to Dim
selector:
entity:
domain: light
default: ""
button3_dim_step:
name: Dim Step Percent
description: Change light Brightness this amount per dim cycle. (1 to 50)
selector:
number:
min: 1
max: 50
unit_of_measurement: '%'
default: 2
button3_dim_delay:
name: Dim Interval (seconds)
description: Time between each dim cycle. (0.05 to 2.0)
selector:
number:
min: 0.05
max: 2
unit_of_measurement: seconds
default: 0.2
button3_boundary:
name: Dim Boundary Percent
description: At Dim Start, if the light is Below this Brightness Level, the dim will Increase Brightness, otherwise it will Decreases Brightness
selector:
number:
min: 0
max: 100
unit_of_measurement: '%'
default: 50
button4_basic_actions:
name: "🔘 Button 4 - Basic Actions"
description: Configure basic button press actions
collapsed: true
input:
button4_single:
name: Single Short Press
selector:
action: {}
default: []
button4_double:
name: Double Short Press
selector:
action: {}
default: []
button4_triple:
name: Triple Short Press
selector:
action: {}
default: []
button4_down:
name: Button Down
selector:
action: {}
default: []
button4_up:
name: Button Up
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button4_long:
name: Long Press
description: when Dimming Function enabled, this setting is ignored.
selector:
action: {}
default: []
button4_dim_settings:
name: "💡 Button 4 - Dimming Settings"
description: Configure dimming functionality for long press
collapsed: true
input:
button4_dim_enabled:
name: Enable Dim Function
description: When enabled the above actions for Long Press and Button Up are Disabled
selector:
boolean: {}
default: false
button4_dim_target:
name: Light Entity or Group you want to Dim
selector:
entity:
domain: light
default: ""
button4_dim_step:
name: Dim Step Percent
description: Change light Brightness this amount per dim cycle. (1 to 50)
selector:
number:
min: 1
max: 50
unit_of_measurement: '%'
default: 2
button4_dim_delay:
name: Dim Interval (seconds)
description: Time between each dim cycle. (0.05 to 2.0)
selector:
number:
min: 0.05
max: 2
unit_of_measurement: seconds
default: 0.2
button4_boundary:
name: Dim Boundary Percent
description: At Dim Start, if the light is Below this Brightness Level, the dim will Increase Brightness, otherwise it will Decreases Brightness
selector:
number:
min: 0
max: 100
unit_of_measurement: '%'
default: 50
mode: restart
max_exceeded: silent
trigger:
# Button 1 Triggers
- platform: device
device_id: !input shelly_device
domain: shelly
type: single_push
subtype: button1
id: btn1_single
- platform: device
device_id: !input shelly_device
domain: shelly
type: double_push
subtype: button1
id: btn1_double
- platform: device
device_id: !input shelly_device
domain: shelly
type: triple_push
subtype: button1
id: btn1_triple
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_down
subtype: button1
id: btn1_down
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_up
subtype: button1
id: btn1_up
- platform: device
device_id: !input shelly_device
domain: shelly
type: long_push
subtype: button1
id: btn1_long
# Button 2 Triggers
- platform: device
device_id: !input shelly_device
domain: shelly
type: single_push
subtype: button2
id: btn2_single
- platform: device
device_id: !input shelly_device
domain: shelly
type: double_push
subtype: button2
id: btn2_double
- platform: device
device_id: !input shelly_device
domain: shelly
type: triple_push
subtype: button2
id: btn2_triple
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_down
subtype: button2
id: btn2_down
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_up
subtype: button2
id: btn2_up
- platform: device
device_id: !input shelly_device
domain: shelly
type: long_push
subtype: button2
id: btn2_long
# Button 3 Triggers
- platform: device
device_id: !input shelly_device
domain: shelly
type: single_push
subtype: button3
id: btn3_single
- platform: device
device_id: !input shelly_device
domain: shelly
type: double_push
subtype: button3
id: btn3_double
- platform: device
device_id: !input shelly_device
domain: shelly
type: triple_push
subtype: button3
id: btn3_triple
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_down
subtype: button3
id: btn3_down
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_up
subtype: button3
id: btn3_up
- platform: device
device_id: !input shelly_device
domain: shelly
type: long_push
subtype: button3
id: btn3_long
# Button 4 Triggers
- platform: device
device_id: !input shelly_device
domain: shelly
type: single_push
subtype: button4
id: btn4_single
- platform: device
device_id: !input shelly_device
domain: shelly
type: double_push
subtype: button4
id: btn4_double
- platform: device
device_id: !input shelly_device
domain: shelly
type: triple_push
subtype: button4
id: btn4_triple
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_down
subtype: button4
id: btn4_down
- platform: device
device_id: !input shelly_device
domain: shelly
type: btn_up
subtype: button4
id: btn4_up
- platform: device
device_id: !input shelly_device
domain: shelly
type: long_push
subtype: button4
id: btn4_long
variables:
dimming_active: false
button1_dim_enabled: !input button1_dim_enabled
button1_dim_target: !input button1_dim_target
button1_dim_step: !input button1_dim_step
button1_dim_delay: !input button1_dim_delay
button1_boundary: !input button1_boundary
button2_dim_enabled: !input button2_dim_enabled
button2_dim_target: !input button2_dim_target
button2_dim_step: !input button2_dim_step
button2_dim_delay: !input button2_dim_delay
button2_boundary: !input button2_boundary
button3_dim_enabled: !input button3_dim_enabled
button3_dim_target: !input button3_dim_target
button3_dim_step: !input button3_dim_step
button3_dim_delay: !input button3_dim_delay
button3_boundary: !input button3_boundary
button4_dim_enabled: !input button4_dim_enabled
button4_dim_target: !input button4_dim_target
button4_dim_step: !input button4_dim_step
button4_dim_delay: !input button4_dim_delay
button4_boundary: !input button4_boundary
action:
- choose:
# BUTTON 1 SINGLE
- conditions:
- condition: trigger
id: btn1_single
sequence: !input button1_single
# BUTTON 1 DOUBLE
- conditions:
- condition: trigger
id: btn1_double
sequence: !input button1_double
# BUTTON 1 TRIPLE
- conditions:
- condition: trigger
id: btn1_triple
sequence: !input button1_triple
# BUTTON 1 DOWN
- conditions:
- condition: trigger
id: btn1_down
sequence: !input button1_down
# BUTTON 1 UP
- conditions:
- condition: trigger
id: btn1_up
sequence:
- variables:
dimming_active: false
# BUTTON 1 LONG
- conditions:
- condition: trigger
id: btn1_long
sequence:
- if:
- condition: and
conditions:
- condition: template
value_template: "{{ button1_dim_enabled == true }}"
- condition: template
value_template: "{{ button1_dim_target is defined and button1_dim_target != '' }}"
then:
# TURN ON IF OFF
- if:
- condition: template
value_template: "{{ is_state(button1_dim_target, 'off') }}"
then:
- service: light.turn_on
target:
entity_id: "{{ button1_dim_target }}"
# CALCULATE DIRECTION
- variables:
current_brightness: "{{ state_attr(button1_dim_target, 'brightness') | default(255) }}"
start_brightness: "{{ current_brightness | int }}"
start_pct: "{{ (start_brightness / 255 * 100) | round(0) }}"
brightness_step_value: "{{ (button1_dim_step | float / 100 * 255) | round(0) }}"
button1_dim_direction: "{%- if start_pct < button1_boundary -%}+{%- else -%}-{%- endif -%}"
# START DIM LOOP
- variables:
dimming_active: true
- repeat:
while:
- condition: template
value_template: "{{ dimming_active }}"
sequence:
- service: light.turn_on
target:
entity_id: "{{ button1_dim_target }}"
data:
brightness_step: "{{ button1_dim_direction }}{{ brightness_step_value }}"
- delay:
seconds: "{{ button1_dim_delay }}"
# BUTTON 2 SINGLE
- conditions:
- condition: trigger
id: btn2_single
sequence: !input button2_single
# BUTTON 2 DOUBLE
- conditions:
- condition: trigger
id: btn2_double
sequence: !input button2_double
# BUTTON 2 TRIPLE
- conditions:
- condition: trigger
id: btn2_triple
sequence: !input button2_triple
# BUTTON 2 DOWN
- conditions:
- condition: trigger
id: btn2_down
sequence: !input button2_down
# BUTTON 2 UP
- conditions:
- condition: trigger
id: btn2_up
sequence:
- variables:
dimming_active: false
# BUTTON 2 LONG
- conditions:
- condition: trigger
id: btn2_long
sequence:
- if:
- condition: and
conditions:
- condition: template
value_template: "{{ button2_dim_enabled == true }}"
- condition: template
value_template: "{{ button2_dim_target is defined and button2_dim_target != '' }}"
then:
# TURN ON IF OFF
- if:
- condition: template
value_template: "{{ is_state(button2_dim_target, 'off') }}"
then:
- service: light.turn_on
target:
entity_id: "{{ button2_dim_target }}"
# CALCULATE DIRECTION
- variables:
current_brightness: "{{ state_attr(button2_dim_target, 'brightness') | default(255) }}"
start_brightness: "{{ current_brightness | int }}"
start_pct: "{{ (start_brightness / 255 * 100) | round(0) }}"
brightness_step_value: "{{ (button2_dim_step | float / 100 * 255) | round(0) }}"
button2_dim_direction: "{%- if start_pct < button2_boundary -%}+{%- else -%}-{%- endif -%}"
# START DIM LOOP
- variables:
dimming_active: true
- repeat:
while:
- condition: template
value_template: "{{ dimming_active }}"
sequence:
- service: light.turn_on
target:
entity_id: "{{ button2_dim_target }}"
data:
brightness_step: "{{ button2_dim_direction }}{{ brightness_step_value }}"
- delay:
seconds: "{{ button2_dim_delay }}"
# BUTTON 3 SINGLE
- conditions:
- condition: trigger
id: btn3_single
sequence: !input button3_single
# BUTTON 3 DOUBLE
- conditions:
- condition: trigger
id: btn3_double
sequence: !input button3_double
# BUTTON 3 TRIPLE
- conditions:
- condition: trigger
id: btn3_triple
sequence: !input button3_triple
# BUTTON 3 DOWN
- conditions:
- condition: trigger
id: btn3_down
sequence: !input button3_down
# BUTTON 3 UP
- conditions:
- condition: trigger
id: btn3_up
sequence:
- variables:
dimming_active: false
# BUTTON 3 LONG
- conditions:
- condition: trigger
id: btn3_long
sequence:
- if:
- condition: and
conditions:
- condition: template
value_template: "{{ button3_dim_enabled == true }}"
- condition: template
value_template: "{{ button3_dim_target is defined and button3_dim_target != '' }}"
then:
# TURN ON IF OFF
- if:
- condition: template
value_template: "{{ is_state(button3_dim_target, 'off') }}"
then:
- service: light.turn_on
target:
entity_id: "{{ button3_dim_target }}"
# CALCULATE DIRECTION
- variables:
current_brightness: "{{ state_attr(button3_dim_target, 'brightness') | default(255) }}"
start_brightness: "{{ current_brightness | int }}"
start_pct: "{{ (start_brightness / 255 * 100) | round(0) }}"
brightness_step_value: "{{ (button3_dim_step | float / 100 * 255) | round(0) }}"
button3_dim_direction: "{%- if start_pct < button3_boundary -%}+{%- else -%}-{%- endif -%}"
# START DIM LOOP
- variables:
dimming_active: true
- repeat:
while:
- condition: template
value_template: "{{ dimming_active }}"
sequence:
- service: light.turn_on
target:
entity_id: "{{ button3_dim_target }}"
data:
brightness_step: "{{ button3_dim_direction }}{{ brightness_step_value }}"
- delay:
seconds: "{{ button3_dim_delay }}"
# BUTTON 4 SINGLE
- conditions:
- condition: trigger
id: btn4_single
sequence: !input button4_single
# BUTTON 4 DOUBLE
- conditions:
- condition: trigger
id: btn4_double
sequence: !input button4_double
# BUTTON 4 TRIPLE
- conditions:
- condition: trigger
id: btn4_triple
sequence: !input button4_triple
# BUTTON 4 DOWN
- conditions:
- condition: trigger
id: btn4_down
sequence: !input button4_down
# BUTTON 4 UP
- conditions:
- condition: trigger
id: btn4_up
sequence:
- variables:
dimming_active: false
# BUTTON 4 LONG
- conditions:
- condition: trigger
id: btn4_long
sequence:
- if:
- condition: and
conditions:
- condition: template
value_template: "{{ button4_dim_enabled == true }}"
- condition: template
value_template: "{{ button4_dim_target is defined and button4_dim_target != '' }}"
then:
# TURN ON IF OFF
- if:
- condition: template
value_template: "{{ is_state(button4_dim_target, 'off') }}"
then:
- service: light.turn_on
target:
entity_id: "{{ button4_dim_target }}"
# CALCULATE DIRECTION
- variables:
current_brightness: "{{ state_attr(button4_dim_target, 'brightness') | default(255) }}"
start_brightness: "{{ current_brightness | int }}"
start_pct: "{{ (start_brightness / 255 * 100) | round(0) }}"
brightness_step_value: "{{ (button4_dim_step | float / 100 * 255) | round(0) }}"
button4_dim_direction: "{%- if start_pct < button4_boundary -%}+{%- else -%}-{%- endif -%}"
# START DIM LOOP
- variables:
dimming_active: true
- repeat:
while:
- condition: template
value_template: "{{ dimming_active }}"
sequence:
- service: light.turn_on
target:
entity_id: "{{ button4_dim_target }}"
data:
brightness_step: "{{ button4_dim_direction }}{{ brightness_step_value }}"
- delay:
seconds: "{{ button4_dim_delay }}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment