This is based on another blueprint which I unfortunately are no longer able to find - arrrgh…
I set my Bilresa switch from matter to zigbee. The mentioned blueprint was only capable of switching lamps on/off but the whell did not have any effect on brightness.
The blueprint here - made by Gemini with only some short prompts, works flawless for me.
blueprint:
name: Bilresa Scroll Controller V2 (Direct & Clean)
author: whag (patched)
description: >
Steuert Licht, Media oder Klima über den IKEA Bilresa (Zigbee2MQTT).
Behebt den Konflikt zwischen Tasten und Drehrad sowie das Verschlucken von Dimm-Schritten.
domain: automation
input:
mqtt_topic:
name: MQTT Topic
description: "Das Zigbee2MQTT Topic deines Schalters (z.B. zigbee2mqtt/bilresa_wohnzimmer)."
default: "zigbee2mqtt/FRIENDLY_NAME_HERE"
selector:
text:
controlled_entity:
name: Entity to Control
description: "Die zu steuernden Entitäten (Licht, Media Player oder Klima)."
selector:
entity:
domain: [light, media_player, climate]
multiple: true
control_mode:
name: Control Mode
description: "Wähle, wie das Drehrad regeln soll."
default: light_brightness_direct
selector:
select:
options:
- {label: "Light - Brightness (Direct 1:1 Level)", value: light_brightness_direct}
- {label: "Light - Brightness (Relative Steps)", value: light_brightness}
- {label: "Light - Colour Temp", value: light_temp}
- {label: "Light - Colour Wheel (RGB)", value: light_color}
- {label: "Media Volume", value: media}
- {label: "Climate Temperature", value: climate}
step_brightness:
name: Brightness Step Percentage
description: "Prozentuale Änderung pro Dreh-Impuls (nur für Relative Steps)."
default: 15
selector:
number: {min: 1, max: 100, step: 1, unit_of_measurement: "%"}
step_temp:
name: Colour Temp Step
description: "Mired-Schritte pro Dreh-Impuls."
default: 30
selector:
number: {min: 1, max: 100, step: 1}
step_color:
name: Colour Hue Step
description: "Grad-Schritte auf dem Farbkreis (1-360)."
default: 15
selector:
number: {min: 1, max: 360, step: 1, unit_of_measurement: "°"}
step_media:
name: Volume Step Percentage
description: "Lautstärke-Änderung pro Impuls (0.01 bis 0.2)."
default: 0.05
selector:
number: {min: 0.01, max: 0.2, step: 0.01}
step_climate:
name: Temperature Step
description: "Temperatur-Schritte in °C."
default: 0.5
selector:
number: {min: 0.1, max: 5, step: 0.1, unit_of_measurement: "°C"}
session_timeout:
name: Session Timeout
description: "Sekunden für fortlaufende Dreh-Erkennung (für Relative Steps)."
default: 2
selector:
number: {min: 0.5, max: 5, step: 0.5, unit_of_measurement: "s"}
action_single_on: {name: Single On, default: [], selector: {action: {}}}
action_single_off: {name: Single Off, default: [], selector: {action: {}}}
action_double_on: {name: Double On, default: [], selector: {action: {}}}
action_double_off: {name: Double Off, default: [], selector: {action: {}}}
mode: queued
max: 10
max_exceeded: silent
trigger:
- platform: mqtt
id: "trig_on"
topic: !input mqtt_topic
payload: "on"
value_template: "{{ value_json.action }}"
- platform: mqtt
id: "trig_off"
topic: !input mqtt_topic
payload: "off"
value_template: "{{ value_json.action }}"
- platform: mqtt
id: "trig_on_double"
topic: !input mqtt_topic
payload: "on_double"
value_template: "{{ value_json.action }}"
- platform: mqtt
id: "trig_off_double"
topic: !input mqtt_topic
payload: "off_double"
value_template: "{{ value_json.action }}"
- platform: mqtt
id: "trig_scroll"
topic: !input mqtt_topic
payload: "brightness_move_to_level"
value_template: "{{ value_json.action }}"
variables:
target_entity: !input controlled_entity
mode: !input control_mode
s_bright: !input step_brightness
s_temp: !input step_temp
s_color: !input step_color
s_media: !input step_media
s_climate: !input step_climate
action:
- choose:
- conditions: "{{ trigger.id == 'trig_on' }}"
sequence: !input action_single_on
- conditions: "{{ trigger.id == 'trig_off' }}"
sequence: !input action_single_off
- conditions: "{{ trigger.id == 'trig_on_double' }}"
sequence: !input action_double_on
- conditions: "{{ trigger.id == 'trig_off_double' }}"
sequence: !input action_double_off
- conditions: "{{ trigger.id == 'trig_scroll' }}"
sequence:
- variables:
lvl: >
{{ trigger.payload_json.action_level if trigger.payload_json.action_level is defined else trigger.payload_json.brightness }}
new_val: "{{ 255 if lvl is none else lvl | int }}"
# Aktuelle Helligkeit der Lampe als Referenz für Richtung heranziehen, falls Bilresa keinen Startwert liefert
first_light: "{{ target_entity[0] if target_entity is iterable and target_entity is not string else target_entity }}"
current_light_bri: "{{ state_attr(first_light, 'brightness') | int(128) }}"
direction: >
{% if new_val >= 254 %} 1
{% elif new_val <= 5 %} -1
{% elif new_val > current_light_bri %} 1
{% else %} -1 {% endif %}
- choose:
# 1. DIREKTE 1:1 ÜBERNAHME (Empfohlen für Bilresa)
- conditions: "{{ mode == 'light_brightness_direct' }}"
sequence:
- service: light.turn_on
target:
entity_id: !input controlled_entity
data:
brightness: "{{ [1, [new_val, 255] | min] | max }}"
transition: 0.2
# 2. RELATIVE SCHRITTE
- conditions: "{{ mode == 'light_brightness' }}"
sequence:
- service: light.turn_on
target:
entity_id: !input controlled_entity
data:
brightness_step_pct: "{{ s_bright * direction }}"
transition: 0.2
- conditions: "{{ mode == 'light_temp' }}"
sequence:
- service: light.turn_on
target:
entity_id: !input controlled_entity
data:
color_temp: >
{% set current = state_attr(first_light, 'color_temp') | int(370) %}
{% set min_m = state_attr(first_light, 'min_mireds') | int(153) %}
{% set max_m = state_attr(first_light, 'max_mireds') | int(500) %}
{{ [min_m, [current - (s_temp * direction), max_m]|min]|max }}
transition: 0.2
- conditions: "{{ mode == 'light_color' }}"
sequence:
- service: light.turn_on
target:
entity_id: !input controlled_entity
data:
hs_color:
- "{{ ( (state_attr(first_light, 'hs_color')[0] | default(0) | float) + (s_color * direction) ) % 360 }}"
- "{{ (state_attr(first_light, 'hs_color')[1] | default(100) | float) }}"
transition: 0.2
- conditions: "{{ mode == 'media' }}"
sequence:
- service: >
{% if direction == 1 %} media_player.volume_up
{% else %} media_player.volume_down {% endif %}
target:
entity_id: !input controlled_entity
- conditions: "{{ mode == 'climate' }}"
sequence:
- service: climate.set_temperature
target:
entity_id: !input controlled_entity
data:
temperature: "{{ state_attr(first_light, 'temperature') | float(20) + (s_climate * direction) }}"