As a long-time user of smart lighting solutions, I’ve been experimenting with integrating my IKEA STYRBAR (E2001/E2002) with a CCT LED strip through Zigbee2MQTT. The goal was to mimic the behavior of IKEA lights and controllers, creating a seamless experience with three scenes: warm, normal, and cold. While the setup seemed straightforward, there were a few hurdles to overcome.
Initially, I connected the CCT LED strip to a Shelly RGBW2, assigning each channel to warm and cold white separately. The challenge was to combine these into a single light entity controlled by the STYRBAR. After some research, I discovered that manually creating a scene helper of type input number with a range from 0 to 1 was the key to achieving the desired functionality.
Here’s a simplified version of the automation I implemented:
yaml
alias: Downstair bathroom mirror light controller
description: “”
trigger:
- platform: state
entity_id:- sensor.potatozeta_action
attribute: action
to: - “on”
- “off”
- arrow_left_click
- arrow_right_click
- brightness_move_down
- brightness_move_up
- brightness_stop
condition:
action:
- sensor.potatozeta_action
- variables:
command: “{{ trigger.to_state.state }}”
low_brightness: 1
default_brightness: 20
high_brightness: 100
step_pct: 5
speed: 300
warm_channel: light.downstairs_bathroom_channel_4
cold_channel: light.downstairs_bathroom_channel_3
scene: “{{ states(‘input_number.mirror_scene’) | int }}”
current_visible_brightness: >-
{{ (state_attr(‘light.downstair_bathroom_mirror’, ‘brightness’) or 0) / 2.55 }} - choose:
- conditions:
- condition: template
value_template: “{{ command == ‘on’ }}”
sequence: - service: light.turn_on
target:
entity_id: |{% if scene == 0 %} {{ warm_channel }}{% elif scene == 1 %} {{ warm_channel }}, {{ cold_channel }}{% elif scene == 2 %} {{ cold_channel }}{% endif %}
data:
brightness_pct: “{{ default_brightness }}”
- condition: template
- conditions:
- condition: template
value_template: “{{ command == ‘off’ }}”
sequence: - service: light.turn_off
target:
entity_id: |{% if scene == 0 %} {{ warm_channel }}{% elif scene == 1 %} {{ warm_channel }}, {{ cold_channel }}{% elif scene == 2 %} {{ cold_channel }}{% endif %}
- condition: template
- conditions:
- condition: template
value_template: “{{ command == ‘brightness_move_up’ }}”
sequence: - repeat:
while:
sequence:
- service: light.turn_on
target:
entity_id: |{% if scene == 0 %} {{ warm_channel }}{% elif scene == 1 %} {{ warm_channel }}, {{ cold_channel }}{% elif scene == 2 %} {{ cold_channel }}{% endif %}
data:
brightness_step_pct: “{{ step_pct | int }}”
transition: “{{ (speed / 1000) | float }}”
- delay:
milliseconds: “{{ speed }}”
- condition: template
- conditions:
- condition: template
value_template: “{{ command == ‘brightness_move_down’ }}”
sequence: - repeat:
while:
sequence:
- variables:
current_brightness_warm: “{{ (state_attr(warm_channel, ‘brightness’) or 0) | int }}”
current_brightness_cold: “{{ (state_attr(cold_channel, ‘brightness’) or 0) | int }}”
new_brightness_warm: >-
{{ [current_brightness_warm - (step_pct * 2.55), low_brightness * 2.55] | max }}
new_brightness_cold: >-
{{ [current_brightness_cold - (step_pct * 2.55), low_brightness * 2.55] | max }}
new_brightness: “{{ [new_brightness_cold, new_brightness_warm] | min}}”
- service: light.turn_on
target:
entity_id: >{% set warm_on = is_state(warm_channel, ‘on’) %}{% set cold_on = is_state(cold_channel, ‘on’) %}{% if warm_on and cold_on %} {{ [warm_channel, cold_channel] | join(', ') }}{% elif warm_on %} {{ warm_channel }}{% elif cold_on %} {{ cold_channel }}{% else %} none{% endif %}
data:
brightness: “{{ new_brightness }}”
transition: “{{ (speed / 1000) | float }}”
- delay:
milliseconds: “{{ speed }}”
- condition: template
- conditions:
- condition: template
value_template: “{{ command == ‘arrow_right_click’ }}”
sequence: - choose:
- conditions:
- condition: template
value_template: “{{ scene < 2 }}”
sequence: - service: input_number.set_value
target:
entity_id: input_number.mirror_scene
data:
value: “{{ scene + 1 }}”
- condition: template
- choose:
- conditions:
- condition: template
value_template: “{{ (scene == 0) }}”
sequence:
parallel:- service: light.turn_on
target:
entity_id:
- “{{ cold_channel }}”
- “{{ warm_channel }}”
data:
brightness_pct: “{{ current_visible_brightness }}”
- service: light.turn_on
- condition: template
- conditions:
- condition: template
value_template: “{{ scene == 2 or scene == 1 }}”
sequence: - service: light.turn_on
target:
entity_id: “{{ cold_channel }}”
data:
brightness_pct: “{{ current_visible_brightness }}” - service: light.turn_off
target:
entity_id: “{{ warm_channel }}”
- condition: template
- conditions:
- conditions:
- condition: template
- conditions:
- condition: template
value_template: “{{ command == ‘arrow_left_click’ }}”
sequence: - choose:
- conditions:
- condition: template
value_template: “{{ scene > 0 }}”
sequence: - service: input_number.set_value
target:
entity_id: input_number.mirror_scene
data:
value: “{{ scene - 1 }}”
- condition: template
- choose:
- conditions:
- condition: template
value_template: “{{ (scene == 0) or (scene == 1) }}”
sequence:
parallel:- service: light.turn_on
target:
entity_id: “{{ warm_channel }}”
data:
brightness_pct: “{{ current_visible_brightness }}” - service: light.turn_off
target:
entity_id: “{{ cold_channel }}”
- service: light.turn_on
- condition: template
- conditions:
- condition: template
value_template: “{{ scene == 2 }}”
sequence: - service: light.turn_on
target:
entity_id:
- “{{ warm_channel }}”
- “{{ cold_channel }}”
data:
brightness_pct: “{{ current_visible_brightness }}”
default:
mode: restart
- condition: template
- conditions:
- conditions:
- condition: template
- conditions:
This setup allows for smooth transitions between scenes and brightness levels, all controlled seamlessly by the STYRBAR. The key takeaway is that with a bit of configuration and automation, even basic hardware can be transformed into a sophisticated smart lighting system. If anyone has questions or suggestions for improvement, I’d love to hear them!
#SmartLighting Zigbee2MQTT ikea HomeAutomation