Files
Home-Assistant/blueprints/automation/thetestspecimen/ikea-bilresa-scroll-wheel.yaml
T
2026-07-14 23:57:03 -04:00

921 lines
28 KiB
YAML

blueprint:
name: IKEA Bilresa Scrollwheel - Light Control
author: thetestspecimen
source_url: https://github.com/thetestspecimen/homeassistant/blob/main/blueprints/ikea-bilresa-scroll-wheel.yaml
description: "\n# \U0001F4A1 Light controller \U0001F4A1\n## IKEA BILRESA - Smart
Scroll Wheel utilising Matter over Thread\n\n\n## VARIABLES:\n- 3 Scroll Zones:
Choose the function (Brightness, Kelvin, RGB, Presets).\n- 3 Buttons x 3 Gestures:
Choose a specific action for EACH gesture (double click / triple click / hold).\n\n***Note:***
single click will always toggle the light on or off.\n\n## REQUIREMENTS:\n\nFor
optimal behavior, the following settings must be applied:\n- ENABLE Events: 3,6,9
(in section \"Events\")\n- ENABLE Sensors: 1,2,4,5,7,8 (in section \"Diagnostic\")\n-
DISABLE Events: 1,2,4,5,7,8 (in section \"Events\")\n- DISABLE Sensors: 3,6,9
(in section \"Diagnostic\")\n\n***Note:*** this blueprint cannot be used with
the BILRESA 2-Button Remote.\n"
homeassistant:
min_version: 2024.6.0
domain: automation
input:
header_entity_mapping:
name: Entity Mapping [REQUIRED]
description: Select the entities for the scroll wheel and buttons
default: ''
selector:
constant:
value: ''
group_buttons:
name: Buttons
icon: mdi:gesture-tap
collapsed: true
input:
event_button_1:
name: 'Channel 1: Button'
description: 'Event: Look for ''Button (3)'''
selector:
entity:
filter:
- domain:
- event
integration: matter
device_class:
- button
multiple: false
reorder: false
event_button_2:
name: 'Channel 2: Button'
description: 'Event: Look for ''Button (6)'''
selector:
entity:
filter:
- domain:
- event
integration: matter
device_class:
- button
multiple: false
reorder: false
event_button_3:
name: 'Channel 3: Button'
description: 'Event: Look for ''Button (9)'''
selector:
entity:
filter:
- domain:
- event
integration: matter
device_class:
- button
multiple: false
reorder: false
group_scroll_wheel:
name: Scroll Wheel
icon: mdi:rotate-right
collapsed: true
input:
sensor_1:
name: 'Channel 1: Scroll forwards'
description: 'Sensor: Look for ''Current switch position (1)'''
selector:
entity:
filter:
- domain:
- sensor
integration: matter
multiple: false
reorder: false
sensor_2:
name: 'Channel 1: Scroll backwards'
description: 'Sensor: Look for ''Current switch position (2)'''
selector:
entity:
filter:
- domain:
- sensor
integration: matter
multiple: false
reorder: false
sensor_4:
name: 'Channel 2: Scroll forwards'
description: 'Sensor: Look for ''Current switch position (4)'''
selector:
entity:
filter:
- domain:
- sensor
integration: matter
multiple: false
reorder: false
sensor_5:
name: 'Channel 2: Scroll backwards'
description: 'Sensor: Look for ''Current switch position (5)'''
selector:
entity:
filter:
- domain:
- sensor
integration: matter
multiple: false
reorder: false
sensor_7:
name: 'Channel 3: Scroll forwards'
description: 'Sensor: Look for ''Current switch position (7)'''
selector:
entity:
filter:
- domain:
- sensor
integration: matter
multiple: false
reorder: false
sensor_8:
name: 'Channel 3: Scroll backwards'
description: 'Sensor: Look for ''Current switch position (8)'''
selector:
entity:
filter:
- domain:
- sensor
integration: matter
multiple: false
reorder: false
header_default_light:
name: Default Light
default: ''
selector:
constant:
value: ''
global_light:
name: Global Light - Default [REQUIRED]
description: This light will be used for any zone or button that does not have
a specific override light set below.
selector:
entity:
domain:
- light
multiple: true
reorder: false
header_1:
name: Channel 1
default: ''
selector:
constant:
value: ''
group_scroll_1:
name: Scroll Wheel Settings
icon: mdi:rotate-right
collapsed: true
input:
light_z1:
name: Light (Scroll - Channel 1) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
scroll_logic_1_2:
name: Scroll - Channel 1
description: Sensors 1 & 2
default: brightness
selector:
select:
options:
- label: Brightness (Bright / Dark)
value: brightness
- label: Kelvin (Cool / Warm)
value: kelvin
- label: RGB Colour (Rainbow)
value: rgb
- label: Presets (Work / Cozy)
value: preset
sort: false
custom_value: false
multiple: false
group_button_1_single:
name: 'Button 1: Single Click (Toggle On/Off)'
icon: mdi:gesture-tap
collapsed: true
input:
light_b1_single:
name: Light (Button 1 Single Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
group_button_1_double:
name: 'Button 1: Double Click'
icon: mdi:gesture-double-tap
collapsed: true
input:
light_b1_double:
name: Light (Button 1 Double Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn1_double_bright:
name: 'Button 1: Double Click Brightness (%)'
default: 80
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn1_double_temp:
name: 'Button 1: Double Click Colour Temp (K)'
default: 4000
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
group_button_1_triple:
name: 'Button 1: Triple Click'
icon: mdi:gesture-tap
collapsed: true
input:
light_b1_triple:
name: Light (Button 1 Triple Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn1_triple_bright:
name: 'Button 1: Triple Click Brightness (%)'
default: 100
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn1_triple_temp:
name: 'Button 1: Triple Click Colour Temp (K)'
default: 6000
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
group_button_1_hold:
name: 'Button 1: Hold'
icon: mdi:gesture-tap-hold
collapsed: true
input:
light_b1_hold:
name: Light (Button 1 Hold) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn1_hold_bright:
name: 'Button 1: Hold Brightness (%)'
default: 20
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn1_hold_temp:
name: 'Button 1: Hold Colour Temp'
default: 2200
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
header_2:
name: Channel 2
default: ''
selector:
constant:
value: ''
group_scroll_2:
name: Scroll Wheel Settings
icon: mdi:rotate-right
collapsed: true
input:
light_z2:
name: Light (Scroll - Channel 2) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
scroll_logic_4_5:
name: Scroll - Channel 2
description: Sensors 4 & 5
default: kelvin
selector:
select:
options:
- label: Brightness (Bright / Dark)
value: brightness
- label: Kelvin (Cool / Warm)
value: kelvin
- label: RGB Colour (Rainbow)
value: rgb
- label: Presets (Work / Cozy)
value: preset
sort: false
custom_value: false
multiple: false
group_button_2_single:
name: 'Button 2: Single Click (Toggle On/Off)'
icon: mdi:gesture-tap
collapsed: true
input:
light_b2_single:
name: Light (Button 2 Single Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
group_button_2_double:
name: 'Button 2: Double Click'
icon: mdi:gesture-double-tap
collapsed: true
input:
light_b2_double:
name: Light (Button 2 Double Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn2_double_bright:
name: 'Button 2: Double Click Brightness (%)'
default: 80
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn2_double_temp:
name: 'Button 2: Double Click Colour Temp (K)'
default: 4000
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
group_button_2_triple:
name: 'Button 2: Triple Click'
icon: mdi:gesture-tap
collapsed: true
input:
light_b2_triple:
name: Light (Button 2 Triple Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn2_triple_bright:
name: 'Button 2: Triple Click Brightness (%)'
default: 100
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn2_triple_temp:
name: 'Button 2: Triple Click Colour Temp (K)'
default: 6000
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
group_button_2_hold:
name: 'Button 2: Hold'
icon: mdi:gesture-tap-hold
collapsed: true
input:
light_b2_hold:
name: Light (Button 2 Hold) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn2_hold_bright:
name: 'Button 2: Hold Brightness (%)'
default: 20
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn2_hold_temp:
name: 'Button 2: Hold Colour Temp (K)'
default: 2200
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
header_3:
name: Channel 3
default: ''
selector:
constant:
value: ''
group_scroll_3:
name: Scroll Wheel Settings
icon: mdi:rotate-right
collapsed: true
input:
light_z3:
name: Light (Scroll - Channel 3) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
scroll_logic_7_8:
name: Scroll - Channel 3
description: Sensors 7 & 8
default: preset
selector:
select:
options:
- label: Brightness (Bright / Dark)
value: brightness
- label: Kelvin (Cool / Warm)
value: kelvin
- label: RGB Colour (Rainbow)
value: rgb
- label: Presets (Work / Cozy)
value: preset
sort: false
custom_value: false
multiple: false
group_button_3_single:
name: 'Button 3: Single Click (Toggle On/Off)'
icon: mdi:gesture-tap
collapsed: true
input:
light_b3_single:
name: Light (Button 3 Single Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
group_button_3_double:
name: 'Button 3: Double Click'
icon: mdi:gesture-double-tap
collapsed: true
input:
light_b3_double:
name: Light (Button 3 Double Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn3_double_bright:
name: 'Button 3: Double Click Brightness (%)'
default: 80
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn3_double_temp:
name: 'Button 3: Double Click Colour Temp (K)'
default: 4000
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
group_button_3_triple:
name: 'Button 3: Triple Click'
icon: mdi:gesture-tap
collapsed: true
input:
light_b3_triple:
name: Light (Button 3 Triple Click) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn3_triple_bright:
name: 'Button 3: Triple Click Brightness (%)'
default: 100
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn3_triple_temp:
name: 'Button 3: Triple Click Colour Temp (K)'
default: 6000
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
group_button_3_hold:
name: 'Button 3: Hold'
icon: mdi:gesture-tap-hold
collapsed: true
input:
light_b3_hold:
name: Light (Button 3 Hold) - Optional Override
default: ''
selector:
entity:
domain:
- light
multiple: true
reorder: false
btn3_hold_bright:
name: 'Button 3: Hold Brightness (%)'
default: 20
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
btn3_hold_temp:
name: 'Button 3: Hold Colour Temp (K)'
default: 2200
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
header_tuning:
name: Fine Tuning
default: ''
selector:
constant:
value: ''
group_step_size:
name: Step Sizes
icon: mdi:tune
collapsed: true
input:
step_pct:
name: 'Step Size: Brightness (%)'
default: 10
selector:
number:
min: 1.0
max: 50.0
unit_of_measurement: '%'
step: 1.0
mode: slider
step_kelvin:
name: 'Step Size: Kelvin (K)'
default: 400
selector:
number:
min: 100.0
max: 1000.0
unit_of_measurement: K
step: 1.0
mode: slider
step_hue:
name: 'Step Size: RGB Hue (°)'
default: 15
selector:
number:
min: 5.0
max: 90.0
unit_of_measurement: °
step: 1.0
mode: slider
group_values:
name: Preset Values
icon: mdi:brightness-6
collapsed: true
input:
val_bright:
name: 'Work: Brightness (%)'
description: The brightness value to use for the 'Work' preset
default: 80
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
val_cold:
name: 'Work: Colour Temperature (K)'
description: The colour temperature value to use for the 'Work' preset
default: 4000
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
val_dim:
name: 'Cozy: Brightness (%)'
description: The brightness value to use for the 'Cozy' preset
default: 20
selector:
number:
min: 1.0
max: 100.0
step: 1.0
mode: slider
val_warm:
name: 'Cozy: Colour Temperature (K)'
description: The colour temperature value to use for the 'Cozy' preset
default: 2200
selector:
color_temp:
unit: kelvin
min: 2000
max: 6500
group_timings:
name: Timings
icon: mdi:clock
collapsed: true
input:
transition_time:
name: Button Transition Time (Seconds)
default: 0.5
selector:
number:
min: 0.0
max: 5.0
step: 0.1
mode: slider
delay_time:
name: Delay (Milliseconds)
description: Delay between command actions. This is effectively button debounce.
default: 150
selector:
number:
min: 0.0
max: 1000.0
step: 10.0
mode: slider
mode: single
max_exceeded: silent
variables:
global_l: !input global_light
l_z1: !input light_z1
l_z2: !input light_z2
l_z3: !input light_z3
l_b1_s: !input light_b1_single
l_b1_d: !input light_b1_double
l_b1_t: !input light_b1_triple
l_b1_h: !input light_b1_hold
l_b2_s: !input light_b2_single
l_b2_d: !input light_b2_double
l_b2_t: !input light_b2_triple
l_b2_h: !input light_b2_hold
l_b3_s: !input light_b3_single
l_b3_d: !input light_b3_double
l_b3_t: !input light_b3_triple
l_b3_h: !input light_b3_hold
m_sc_1: !input scroll_logic_1_2
m_sc_2: !input scroll_logic_4_5
m_sc_3: !input scroll_logic_7_8
b1_d_b: !input btn1_double_bright
b1_d_t: !input btn1_double_temp
b1_t_b: !input btn1_triple_bright
b1_t_t: !input btn1_triple_temp
b1_h_b: !input btn1_hold_bright
b1_h_t: !input btn1_hold_temp
b2_d_b: !input btn2_double_bright
b2_d_t: !input btn2_double_temp
b2_t_b: !input btn2_triple_bright
b2_t_t: !input btn2_triple_temp
b2_h_b: !input btn2_hold_bright
b2_h_t: !input btn2_hold_temp
b3_d_b: !input btn3_double_bright
b3_d_t: !input btn3_double_temp
b3_t_b: !input btn3_triple_bright
b3_t_t: !input btn3_triple_temp
b3_h_b: !input btn3_hold_bright
b3_h_t: !input btn3_hold_temp
s_p: !input step_pct
s_k: !input step_kelvin
s_h: !input step_hue
v_bri: !input val_bright
v_dim: !input val_dim
v_cold: !input val_cold
v_warm: !input val_warm
t_time: !input transition_time
d_time: !input delay_time
id_e1: !input event_button_1
id_e2: !input event_button_2
id_e3: !input event_button_3
triggers:
- trigger: state
entity_id: !input sensor_1
id: sc_1_up
- trigger: state
entity_id: !input sensor_2
id: sc_1_down
- trigger: state
entity_id: !input sensor_4
id: sc_2_down
- trigger: state
entity_id: !input sensor_5
id: sc_2_up
- trigger: state
entity_id: !input sensor_7
id: sc_3_up
- trigger: state
entity_id: !input sensor_8
id: sc_3_down
- trigger: state
entity_id:
- !input event_button_1
- !input event_button_2
- !input event_button_3
id: btn_event
conditions:
- condition: template
value_template: "{{ trigger.from_state is defined and trigger.to_state is defined
and\n trigger.from_state.state not in ['unknown', 'unavailable'] and\n trigger.to_state.state
not in ['unknown', 'unavailable'] and\n trigger.from_state.state != trigger.to_state.state
}}"
actions:
- choose:
- conditions: '{{ ''sc_'' in trigger.id }}'
sequence:
- variables:
target_light: '{{ l_z1 if ''sc_1'' in trigger.id and l_z1 else l_z2 if ''sc_2''
in trigger.id and l_z2 else l_z3 if ''sc_3'' in trigger.id and l_z3 else
global_l }}'
direction: '{{ 1 if ''_up'' in trigger.id else -1 }}'
active_func: '{{ m_sc_1 if ''sc_1'' in trigger.id else m_sc_2 if ''sc_2''
in trigger.id else m_sc_3 }}'
- choose:
- conditions: '{{ active_func == ''brightness'' }}'
sequence:
- action: light.turn_on
target:
entity_id: '{{ target_light }}'
data:
brightness_step_pct: '{{ (s_p | float(default=10)) * direction }}'
transition: 0
- conditions: '{{ active_func == ''kelvin'' }}'
sequence:
- action: light.turn_on
target:
entity_id: '{{ target_light }}'
data:
color_temp_kelvin: '{% set entities = expand(target_light) | map(attribute=''entity_id'')
| list %} {% set first_light = entities[0] if entities else ''light.none''
%} {% set current = state_attr(first_light, ''color_temp_kelvin'') |
int(default=3000) %} {% set step = s_k | int(default=400) %} {% set
min_k = state_attr(first_light, ''min_color_temp_kelvin'') | int(default=2000)
%} {% set max_k = state_attr(first_light, ''max_color_temp_kelvin'')
| int(default=6500) %} {% if direction == 1 %} {{ ([current + step,
max_k] | min) | int }} {% else %} {{ ([current - step, min_k] | max)
| int }} {% endif %}
'
transition: 0
- conditions: '{{ active_func == ''rgb'' }}'
sequence:
- action: light.turn_on
target:
entity_id: '{{ target_light }}'
data:
hs_color: '{% set entities = expand(target_light) | map(attribute=''entity_id'')
| list %} {% set first_light = entities[0] if entities else ''light.none''
%} {% set current_hs = state_attr(first_light, ''hs_color'') %} {% set
h = current_hs[0] | float(default=0) if current_hs is not none else
0 %} {% set s = current_hs[1] | float(default=100) if current_hs is
not none else 100 %} {% set step = s_h | float(default=15) %} {{ [(h
+ (step * direction)) % 360, s] }}
'
transition: 0
- conditions: '{{ active_func == ''preset'' }}'
sequence:
- action: light.turn_on
target:
entity_id: '{{ target_light }}'
data:
brightness_pct: '{{ v_bri if direction == 1 else v_dim }}'
color_temp_kelvin: '{{ v_cold if direction == 1 else v_warm }}'
transition: 1
- choose:
- conditions: '{{ trigger.id == ''btn_event'' }}'
sequence:
- choose:
- conditions: "{{ trigger.to_state.attributes.event_type is defined and \n trigger.to_state.attributes.event_type
== 'multi_press_1' }}\n"
sequence:
- variables:
target_light: '{{ l_b1_s if trigger.entity_id == id_e1 and l_b1_s else
l_b2_s if trigger.entity_id == id_e2 and l_b2_s else l_b3_s if trigger.entity_id
== id_e3 and l_b3_s else global_l }}'
- action: light.toggle
target:
entity_id: '{{ target_light }}'
data:
transition: '{{ t_time }}'
- choose:
- conditions: "{{ trigger.to_state.attributes.event_type is defined and \n trigger.to_state.attributes.event_type
== 'multi_press_2' }}\n"
sequence:
- variables:
target_light: '{{ l_b1_d if trigger.entity_id == id_e1 and l_b1_d else
l_b2_d if trigger.entity_id == id_e2 and l_b2_d else l_b3_d if trigger.entity_id
== id_e3 and l_b3_d else global_l }}'
set_bri: '{{ b1_d_b if trigger.entity_id == id_e1 else b2_d_b if trigger.entity_id
== id_e2 else b3_d_b }}'
set_temp: '{{ b1_d_t if trigger.entity_id == id_e1 else b2_d_t if trigger.entity_id
== id_e2 else b3_d_t }}'
- action: light.turn_on
target:
entity_id: '{{ target_light }}'
data:
brightness_pct: '{{ set_bri }}'
color_temp_kelvin: '{{ set_temp }}'
transition: '{{ t_time }}'
- choose:
- conditions: "{{ trigger.to_state.attributes.event_type is defined and \n trigger.to_state.attributes.event_type
== 'multi_press_3' }}\n"
sequence:
- variables:
target_light: '{{ l_b1_t if trigger.entity_id == id_e1 and l_b1_t else
l_b2_t if trigger.entity_id == id_e2 and l_b2_t else l_b3_t if trigger.entity_id
== id_e3 and l_b3_t else global_l }}'
set_bri: '{{ b1_t_b if trigger.entity_id == id_e1 else b2_t_b if trigger.entity_id
== id_e2 else b3_t_b }}'
set_temp: '{{ b1_t_t if trigger.entity_id == id_e1 else b2_t_t if trigger.entity_id
== id_e2 else b3_t_t }}'
- action: light.turn_on
target:
entity_id: '{{ target_light }}'
data:
brightness_pct: '{{ set_bri }}'
color_temp_kelvin: '{{ set_temp }}'
transition: '{{ t_time }}'
- choose:
- conditions: "{{ trigger.to_state.attributes.event_type is defined and \n trigger.to_state.attributes.event_type
== 'long_press' }}\n"
sequence:
- variables:
target_light: '{{ l_b1_h if trigger.entity_id == id_e1 and l_b1_h else
l_b2_h if trigger.entity_id == id_e2 and l_b2_h else l_b3_h if trigger.entity_id
== id_e3 and l_b3_h else global_l }}'
set_bri: '{{ b1_h_b if trigger.entity_id == id_e1 else b2_h_b if trigger.entity_id
== id_e2 else b3_h_b }}'
set_temp: '{{ b1_h_t if trigger.entity_id == id_e1 else b2_h_t if trigger.entity_id
== id_e2 else b3_h_t }}'
- action: light.turn_on
target:
entity_id: '{{ target_light }}'
data:
brightness_pct: '{{ set_bri }}'
color_temp_kelvin: '{{ set_temp }}'
transition: '{{ t_time }}'
- delay:
milliseconds: '{{ d_time }}'