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