625 lines
21 KiB
YAML
625 lines
21 KiB
YAML
blueprint:
|
|
name: IKEA BILRESA - Light Controller (v1.3)
|
|
description: 'Light control for IKEA BILRESA (Matter). Supports dynamic scrolling,
|
|
scene cycling, and multi-click actions for up to three channels.
|
|
|
|
'
|
|
domain: automation
|
|
input:
|
|
remote_device:
|
|
name: Remote Control
|
|
description: The IKEA BILRESA scroll wheel (Matter) used as the trigger.
|
|
selector:
|
|
device:
|
|
filter:
|
|
- manufacturer: IKEA of Sweden
|
|
model: BILRESA scroll wheel
|
|
multiple: false
|
|
header_1:
|
|
name: Channel 1
|
|
default: ''
|
|
selector:
|
|
constant:
|
|
value: ''
|
|
group_scroll_1:
|
|
name: Scroll Wheel Settings
|
|
icon: mdi:rotate-right
|
|
collapsed: true
|
|
input:
|
|
input_light_1:
|
|
name: Light / Light Group
|
|
description: Select the light or group to be controlled.
|
|
default: {}
|
|
selector:
|
|
target:
|
|
entity:
|
|
- domain:
|
|
- light
|
|
input_mode_1:
|
|
name: Scroll Function
|
|
description: Define which value is changed when turning the wheel.
|
|
default: brightness
|
|
selector:
|
|
select:
|
|
mode: dropdown
|
|
options:
|
|
- label: Brightness
|
|
value: brightness
|
|
- label: Color
|
|
value: hs_color
|
|
- label: Color temperature
|
|
value: temp_kelvin
|
|
custom_value: false
|
|
multiple: false
|
|
sort: false
|
|
input_sens_1:
|
|
name: Multiplier
|
|
description: Define how much the value should change with each scroll step.
|
|
default: 5
|
|
selector:
|
|
number:
|
|
min: 1.0
|
|
max: 50.0
|
|
unit_of_measurement: x
|
|
mode: slider
|
|
step: 1.0
|
|
input_transition_1:
|
|
name: Transition duration
|
|
description: Define how long the transition between changes should take.
|
|
default: 200
|
|
selector:
|
|
number:
|
|
min: 0.0
|
|
max: 5000.0
|
|
unit_of_measurement: ms
|
|
mode: slider
|
|
step: 1.0
|
|
group_single_click_1:
|
|
name: Single Click
|
|
icon: mdi:gesture-tap
|
|
collapsed: true
|
|
input:
|
|
input_click_mode_1:
|
|
name: Click Mode
|
|
description: Choose between a single action or cycling through scenes.
|
|
default: action
|
|
selector:
|
|
select:
|
|
mode: dropdown
|
|
options:
|
|
- label: Perform single action
|
|
value: action
|
|
- label: Scene cycler
|
|
value: scene_cycle
|
|
custom_value: false
|
|
multiple: false
|
|
sort: false
|
|
input_scenes_1:
|
|
name: Scene Selection
|
|
description: Select the scenes to cycle through sequentially.
|
|
default: []
|
|
selector:
|
|
entity:
|
|
domain:
|
|
- scene
|
|
multiple: true
|
|
reorder: false
|
|
input_click_1:
|
|
name: Action on Click
|
|
description: Action to perform when in 'Single Action' mode.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
group_multi_click_1:
|
|
name: Additional Button Functions
|
|
icon: mdi:plus-circle-outline
|
|
collapsed: true
|
|
input:
|
|
input_double_1:
|
|
name: Double Click
|
|
description: Action to perform on double press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_triple_1:
|
|
name: Triple Click
|
|
description: Action to perform on triple press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_long_1:
|
|
name: Hold
|
|
description: Action to perform when holding the button.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_release_1:
|
|
name: Release
|
|
description: Action to perform when releasing the button after a long press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
header_2:
|
|
name: Channel 2
|
|
default: ''
|
|
selector:
|
|
constant:
|
|
value: ''
|
|
group_scroll_2:
|
|
name: Scroll Wheel Settings
|
|
icon: mdi:rotate-right
|
|
collapsed: true
|
|
input:
|
|
input_light_2:
|
|
name: Light / Light Group
|
|
description: Select the light or group to be controlled.
|
|
default: {}
|
|
selector:
|
|
target:
|
|
entity:
|
|
- domain:
|
|
- light
|
|
input_mode_2:
|
|
name: Scroll Function
|
|
description: Define which value is changed when turning the wheel.
|
|
default: brightness
|
|
selector:
|
|
select:
|
|
mode: dropdown
|
|
options:
|
|
- label: Brightness
|
|
value: brightness
|
|
- label: Color
|
|
value: hs_color
|
|
- label: Color temperature
|
|
value: temp_kelvin
|
|
custom_value: false
|
|
multiple: false
|
|
sort: false
|
|
input_sens_2:
|
|
name: Multiplier
|
|
description: Define how much the value should change with each scroll step.
|
|
default: 5
|
|
selector:
|
|
number:
|
|
min: 1.0
|
|
max: 50.0
|
|
unit_of_measurement: x
|
|
mode: slider
|
|
step: 1.0
|
|
input_transition_2:
|
|
name: Transition duration
|
|
description: Define how long the transition between changes should take.
|
|
default: 200
|
|
selector:
|
|
number:
|
|
min: 0.0
|
|
max: 5000.0
|
|
unit_of_measurement: ms
|
|
mode: slider
|
|
step: 1.0
|
|
group_single_click_2:
|
|
name: Single Click
|
|
icon: mdi:gesture-tap
|
|
collapsed: true
|
|
input:
|
|
input_click_mode_2:
|
|
name: Click Mode
|
|
description: Choose between a single action or cycling through scenes.
|
|
default: action
|
|
selector:
|
|
select:
|
|
mode: dropdown
|
|
options:
|
|
- label: Perform single action
|
|
value: action
|
|
- label: Scene cycler
|
|
value: scene_cycle
|
|
custom_value: false
|
|
multiple: false
|
|
sort: false
|
|
input_scenes_2:
|
|
name: Scene Selection
|
|
description: Select the scenes to cycle through sequentially.
|
|
default: []
|
|
selector:
|
|
entity:
|
|
domain:
|
|
- scene
|
|
multiple: true
|
|
reorder: false
|
|
input_click_2:
|
|
name: Action on Click
|
|
description: Action to perform when in 'Single Action' mode.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
group_multi_click_2:
|
|
name: Additional Button Functions
|
|
icon: mdi:plus-circle-outline
|
|
collapsed: true
|
|
input:
|
|
input_double_2:
|
|
name: Double Click
|
|
description: Action to perform on double press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_triple_2:
|
|
name: Triple Click
|
|
description: Action to perform on triple press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_long_2:
|
|
name: Hold
|
|
description: Action to perform when holding the button.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_release_2:
|
|
name: Release
|
|
description: Action to perform when releasing the button after a long press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
header_3:
|
|
name: Channel 3
|
|
default: ''
|
|
selector:
|
|
constant:
|
|
value: ''
|
|
group_scroll_3:
|
|
name: Scroll Wheel Settings
|
|
icon: mdi:rotate-right
|
|
collapsed: true
|
|
input:
|
|
input_light_3:
|
|
name: Light / Light Group
|
|
description: Select the light or group to be controlled.
|
|
default: {}
|
|
selector:
|
|
target:
|
|
entity:
|
|
- domain:
|
|
- light
|
|
input_mode_3:
|
|
name: Scroll Function
|
|
description: Define which value is changed when turning the wheel.
|
|
default: brightness
|
|
selector:
|
|
select:
|
|
mode: dropdown
|
|
options:
|
|
- label: Brightness
|
|
value: brightness
|
|
- label: Color
|
|
value: hs_color
|
|
- label: Color temperature
|
|
value: temp_kelvin
|
|
custom_value: false
|
|
multiple: false
|
|
sort: false
|
|
input_sens_3:
|
|
name: Multiplier
|
|
description: Define how much the value should change with each scroll step.
|
|
default: 5
|
|
selector:
|
|
number:
|
|
min: 1.0
|
|
max: 50.0
|
|
unit_of_measurement: x
|
|
mode: slider
|
|
step: 1.0
|
|
input_transition_3:
|
|
name: Transition duration
|
|
description: Define how long the transition between changes should take.
|
|
default: 200
|
|
selector:
|
|
number:
|
|
min: 0.0
|
|
max: 5000.0
|
|
unit_of_measurement: ms
|
|
mode: slider
|
|
step: 1.0
|
|
group_single_click_3:
|
|
name: Single Click
|
|
icon: mdi:gesture-tap
|
|
collapsed: true
|
|
input:
|
|
input_click_mode_3:
|
|
name: Click Mode
|
|
description: Choose between a single action or cycling through scenes.
|
|
default: action
|
|
selector:
|
|
select:
|
|
mode: dropdown
|
|
options:
|
|
- label: Perform single action
|
|
value: action
|
|
- label: Scene cycler
|
|
value: scene_cycle
|
|
custom_value: false
|
|
multiple: false
|
|
sort: false
|
|
input_scenes_3:
|
|
name: Scene Selection
|
|
description: Select the scenes to cycle through sequentially.
|
|
default: []
|
|
selector:
|
|
entity:
|
|
domain:
|
|
- scene
|
|
multiple: true
|
|
reorder: false
|
|
input_click_3:
|
|
name: Action on Click
|
|
description: Action to perform when in 'Single Action' mode.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
group_multi_click_3:
|
|
name: Additional Button Functions
|
|
icon: mdi:plus-circle-outline
|
|
collapsed: true
|
|
input:
|
|
input_double_3:
|
|
name: Double Click
|
|
description: Action to perform on double press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_triple_3:
|
|
name: Triple Click
|
|
description: Action to perform on triple press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_long_3:
|
|
name: Hold
|
|
description: Action to perform when holding the button.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
input_release_3:
|
|
name: Release
|
|
description: Action to perform when releasing the button after a long press.
|
|
default: []
|
|
selector:
|
|
action: {}
|
|
source_url: https://gist.github.com/SvKRO/52f246362a19f0297fd18969b383181b
|
|
mode: single
|
|
max_exceeded: silent
|
|
trigger_variables:
|
|
var_remote: !input remote_device
|
|
var_events: '{{ device_entities(var_remote) | select(''match'', ''event\.'') | sort
|
|
| list }}
|
|
|
|
'
|
|
temp_kanal1_rechts: '{{ var_events[0] if var_events | length > 0 else ''none'' }}'
|
|
temp_kanal1_links: '{{ var_events[1] if var_events | length > 1 else ''none'' }}'
|
|
temp_kanal1_klick: '{{ var_events[2] if var_events | length > 2 else ''none'' }}'
|
|
temp_kanal2_rechts: '{{ var_events[3] if var_events | length > 3 else ''none'' }}'
|
|
temp_kanal2_links: '{{ var_events[4] if var_events | length > 4 else ''none'' }}'
|
|
temp_kanal2_klick: '{{ var_events[5] if var_events | length > 5 else ''none'' }}'
|
|
temp_kanal3_rechts: '{{ var_events[6] if var_events | length > 6 else ''none'' }}'
|
|
temp_kanal3_links: '{{ var_events[7] if var_events | length > 7 else ''none'' }}'
|
|
temp_kanal3_klick: '{{ var_events[8] if var_events | length > 8 else ''none'' }}'
|
|
trigger:
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal1_links }}'
|
|
id: trigger_kanal1_links
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal1_rechts }}'
|
|
id: trigger_kanal1_rechts
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal1_klick }}'
|
|
id: trigger_kanal1_klick
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal2_links }}'
|
|
id: trigger_kanal2_links
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal2_rechts }}'
|
|
id: trigger_kanal2_rechts
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal2_klick }}'
|
|
id: trigger_kanal2_klick
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal3_links }}'
|
|
id: trigger_kanal3_links
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal3_rechts }}'
|
|
id: trigger_kanal3_rechts
|
|
- trigger: event
|
|
event_type: state_changed
|
|
event_data:
|
|
entity_id: '{{ temp_kanal3_klick }}'
|
|
id: trigger_kanal3_klick
|
|
action:
|
|
- condition: template
|
|
value_template: "{% if trigger.event.data.new_state is none %}\n false\n{% else
|
|
%}\n {% set old_attr = trigger.event.data.old_state.attributes if trigger.event.data.old_state
|
|
is not none else {} %}\n {% set new_attr = trigger.event.data.new_state.attributes
|
|
%}\n {% set old_ts = old_attr.get('last_reported', 'none') %}\n {% set new_ts
|
|
= new_attr.get('last_reported', 'new') %}\n {{ old_ts != new_ts }}\n{% endif
|
|
%}\n"
|
|
- variables:
|
|
m_1: !input input_mode_1
|
|
m_2: !input input_mode_2
|
|
m_3: !input input_mode_3
|
|
s_1: !input input_sens_1
|
|
s_2: !input input_sens_2
|
|
s_3: !input input_sens_3
|
|
l_1: !input input_light_1
|
|
l_2: !input input_light_2
|
|
l_3: !input input_light_3
|
|
tr_1: !input input_transition_1
|
|
tr_2: !input input_transition_2
|
|
tr_3: !input input_transition_3
|
|
action_kanal_id: '{{ trigger.id.split(''_'')[1] }}'
|
|
event_attr: '{{ trigger.event.data.new_state.attributes | to_json | from_json
|
|
}}'
|
|
ticks: '{{ event_attr.get(''totalNumberOfPressesCounted'') | default(1) | int
|
|
}}'
|
|
action_event_type: '{{ event_attr.get(''event_type'') | default(''none'') }}'
|
|
curr_mode: '{% if action_kanal_id == ''kanal1'' %}{{ m_1 }}{% elif action_kanal_id
|
|
== ''kanal2'' %}{{ m_2 }}{% else %}{{ m_3 }}{% endif %}'
|
|
base_sens: '{% if action_kanal_id == ''kanal1'' %}{{ s_1 }}{% elif action_kanal_id
|
|
== ''kanal2'' %}{{ s_2 }}{% else %}{{ s_3 }}{% endif %}'
|
|
step_val: '{% set val = base_sens * ticks %}{{ val if trigger.id.endswith(''_rechts'')
|
|
else val * -1 }}'
|
|
transition_ms: '{% if action_kanal_id == ''kanal1'' %}{{ tr_1 }}{% elif action_kanal_id
|
|
== ''kanal2'' %}{{ tr_2 }}{% else %}{{ tr_3 }}{% endif %}'
|
|
transition_s: '{{ transition_ms / 1000 }}'
|
|
curr_target_obj: '{% if action_kanal_id == ''kanal1'' %}{{ l_1 }} {% elif action_kanal_id
|
|
== ''kanal2'' %}{{ l_2 }} {% else %}{{ l_3 }}{% endif %}
|
|
|
|
'
|
|
curr_target_list: "{% set t = curr_target_obj %} {% set ns = namespace(entities=[])
|
|
%}\n{% set e_ids = t.entity_id if t.entity_id is defined else [] %} {% set ns.entities
|
|
= [e_ids] if e_ids is string else e_ids %}\n{% set d_ids = t.device_id if t.device_id
|
|
is defined else [] %} {% set d_ids = [d_ids] if d_ids is string else d_ids %}
|
|
{% for d in d_ids %}\n {% set ns.entities = ns.entities + (device_entities(d)
|
|
| select('match', 'light\\.') | list) %}\n{% endfor %}\n{% set a_ids = t.area_id
|
|
if t.area_id is defined else [] %} {% set a_ids = [a_ids] if a_ids is string
|
|
else a_ids %} {% for a in a_ids %}\n {% set ns.entities = ns.entities + (area_entities(a)
|
|
| select('match', 'light\\.') | list) %}\n{% endfor %}\n{% set lb_ids = t.label_id
|
|
if t.label_id is defined else [] %} {% set lb_ids = [lb_ids] if lb_ids is string
|
|
else lb_ids %} {% for l in lb_ids %}\n {% set ns.entities = ns.entities + (label_entities(l)
|
|
| select('match', 'light\\.') | list) %}\n{% endfor %}\n{{ ns.entities | unique
|
|
| reject('none') | list }}\n"
|
|
curr_target: '{{ curr_target_list | first | default(''none'') }}'
|
|
- choose:
|
|
- conditions: '{{ trigger.id.endswith(''_rechts'') or trigger.id.endswith(''_links'')
|
|
}}'
|
|
sequence:
|
|
- choose:
|
|
- conditions: '{{ curr_mode == ''brightness'' }}'
|
|
sequence:
|
|
- variables:
|
|
target_value: '{% set current = state_attr(curr_target, ''brightness'')
|
|
| int(128) %} {{ [([current + (step_val | int * 2.55 | int), 0] | max),
|
|
255] | min }}
|
|
|
|
'
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: '{{ curr_target_list }}'
|
|
data:
|
|
transition: '{{ transition_s }}'
|
|
brightness: '{{ target_value }}'
|
|
- conditions: '{{ curr_mode == ''temp_kelvin'' }}'
|
|
sequence:
|
|
- variables:
|
|
target_value: '{% set curr = state_attr(curr_target, ''color_temp_kelvin'')
|
|
| int(3000) %} {% set min_v = state_attr(curr_target, ''min_color_temp_kelvin'')
|
|
| int(2000) %} {% set max_v = state_attr(curr_target, ''max_color_temp_kelvin'')
|
|
| int(6535) %} {{ [([curr + (step_val * 10) | int, min_v] | max), max_v]
|
|
| min }}
|
|
|
|
'
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: '{{ curr_target_list }}'
|
|
data:
|
|
transition: '{{ transition_s }}'
|
|
color_temp_kelvin: '{{ target_value }}'
|
|
- conditions: '{{ curr_mode == ''hs_color'' }}'
|
|
sequence:
|
|
- variables:
|
|
target_value: '{% set hs = state_attr(curr_target, ''hs_color'') | default([0,
|
|
100], true) %} {{ [((hs[0] | float(0) + step_val) % 360) | round(2),
|
|
hs[1] | float(100)] }}
|
|
|
|
'
|
|
- service: light.turn_on
|
|
target:
|
|
entity_id: '{{ curr_target_list }}'
|
|
data:
|
|
transition: '{{ transition_s }}'
|
|
hs_color: '{{ target_value }}'
|
|
- conditions: '{{ trigger.id.endswith(''_klick'') }}'
|
|
sequence:
|
|
- variables:
|
|
cm_1: !input input_click_mode_1
|
|
cm_2: !input input_click_mode_2
|
|
cm_3: !input input_click_mode_3
|
|
cs_1: !input input_scenes_1
|
|
cs_2: !input input_scenes_2
|
|
cs_3: !input input_scenes_3
|
|
c_mode: '{% if action_kanal_id == ''kanal1'' %}{{ cm_1 }}{% elif action_kanal_id
|
|
== ''kanal2'' %}{{ cm_2 }}{% else %}{{ cm_3 }}{% endif %}'
|
|
c_scenes: '{% if action_kanal_id == ''kanal1'' %}{{ cs_1 }}{% elif action_kanal_id
|
|
== ''kanal2'' %}{{ cs_2 }}{% else %}{{ cs_3 }}{% endif %}'
|
|
- choose:
|
|
- conditions: '{{ action_event_type == ''multi_press_1'' }}'
|
|
sequence:
|
|
- choose:
|
|
- conditions: '{{ c_mode == ''scene_cycle'' and c_scenes | count > 0 }}'
|
|
sequence:
|
|
- service: scene.turn_on
|
|
target:
|
|
entity_id: '{% set count = c_scenes | count %}{% set idx = (as_timestamp(now())
|
|
| int // 2) % count %}{{ c_scenes[idx] }}'
|
|
- conditions: '{{ c_mode == ''action'' }}'
|
|
sequence:
|
|
- choose:
|
|
- conditions: '{{ action_kanal_id == ''kanal1'' }}'
|
|
sequence: !input input_click_1
|
|
- conditions: '{{ action_kanal_id == ''kanal2'' }}'
|
|
sequence: !input input_click_2
|
|
- conditions: '{{ action_kanal_id == ''kanal3'' }}'
|
|
sequence: !input input_click_3
|
|
- conditions: '{{ action_event_type == ''multi_press_2'' }}'
|
|
sequence:
|
|
- choose:
|
|
- conditions: '{{ action_kanal_id == ''kanal1'' }}'
|
|
sequence: !input input_double_1
|
|
- conditions: '{{ action_kanal_id == ''kanal2'' }}'
|
|
sequence: !input input_double_2
|
|
- conditions: '{{ action_kanal_id == ''kanal3'' }}'
|
|
sequence: !input input_double_3
|
|
- conditions: '{{ action_event_type == ''multi_press_3'' }}'
|
|
sequence:
|
|
- choose:
|
|
- conditions: '{{ action_kanal_id == ''kanal1'' }}'
|
|
sequence: !input input_triple_1
|
|
- conditions: '{{ action_kanal_id == ''kanal2'' }}'
|
|
sequence: !input input_triple_2
|
|
- conditions: '{{ action_kanal_id == ''kanal3'' }}'
|
|
sequence: !input input_triple_3
|
|
- conditions: '{{ action_event_type == ''long_press'' }}'
|
|
sequence:
|
|
- choose:
|
|
- conditions: '{{ action_kanal_id == ''kanal1'' }}'
|
|
sequence: !input input_long_1
|
|
- conditions: '{{ action_kanal_id == ''kanal2'' }}'
|
|
sequence: !input input_long_2
|
|
- conditions: '{{ action_kanal_id == ''kanal3'' }}'
|
|
sequence: !input input_long_3
|
|
- conditions: '{{ action_event_type == ''long_release'' }}'
|
|
sequence:
|
|
- choose:
|
|
- conditions: '{{ action_kanal_id == ''kanal1'' }}'
|
|
sequence: !input input_release_1
|
|
- conditions: '{{ action_kanal_id == ''kanal2'' }}'
|
|
sequence: !input input_release_2
|
|
- conditions: '{{ action_kanal_id == ''kanal3'' }}'
|
|
sequence: !input input_release_3
|