Last active
August 3, 2025 19:13
-
-
Save JoeCalvert/6b9f60e83c694b22d6d03bd38c1b3cbd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| blueprint: | |
| name: IKEA RODRET Group Controller | |
| author: Joe Calvert | |
| description: Controls accent and main lights with single/double press and brightness control | |
| domain: automation | |
| input: | |
| dimmer_switch: | |
| name: Dimmer Switch | |
| description: The dimmer switch to use as the controller | |
| selector: | |
| device: | |
| filter: | |
| - integration: zha | |
| model: RODRET Dimmer | |
| accent_label: | |
| name: Accent Light Label | |
| description: The label that is applied to the accent lights | |
| selector: | |
| label: {} | |
| main_label: | |
| name: Main Light Label | |
| description: The label that is applied to the main lights | |
| selector: | |
| label: {} | |
| room_area: | |
| name: Room Area | |
| description: Area containing the lights to control | |
| selector: | |
| area: | |
| entity: | |
| domain: | |
| - light | |
| brightness_step: | |
| name: Brightness Step | |
| description: How much to change the brightness per step (1-100) | |
| default: 10 | |
| selector: | |
| number: | |
| min: 1 | |
| max: 100 | |
| brightness_delay: | |
| name: Brightness Change Delay | |
| description: Delay between brightness steps in milliseconds | |
| default: 150 | |
| selector: | |
| number: | |
| min: 100 | |
| max: 2000 | |
| unit_of_measurement: ms | |
| max_loops: | |
| name: Maximum Brightness Loops | |
| description: Maximum number of brightness changes (safety limit) | |
| default: 10 | |
| selector: | |
| number: | |
| min: 5 | |
| max: 100 | |
| variables: | |
| area_id: !input room_area | |
| accent_label_id: !input accent_label | |
| main_label_id: !input main_label | |
| max_loops: !input max_loops | |
| brightness_delay: !input brightness_delay | |
| brightness_step: !input brightness_step | |
| # Get all lights in the specified area | |
| room_lights: >- | |
| {{ expand(area_entities(area_id)) | selectattr('domain', 'eq', 'light') | map(attribute='entity_id') | list }} | |
| # Filter lights by labels | |
| accent_lights: >- | |
| {{ label_entities(accent_label_id) | intersect(room_lights) | list }} | |
| main_lights: >- | |
| {{ label_entities(main_label_id) | intersect(room_lights) | list }} | |
| trigger: | |
| # Single press ON (cluster 6, command "on") | |
| - platform: event | |
| event_type: zha_event | |
| event_data: | |
| device_id: !input dimmer_switch | |
| cluster_id: 6 | |
| command: "on" | |
| id: on_single | |
| # Single press OFF (cluster 6, command "off") | |
| - platform: event | |
| event_type: zha_event | |
| event_data: | |
| device_id: !input dimmer_switch | |
| cluster_id: 6 | |
| command: "off" | |
| id: off_single | |
| # Hold ON (cluster 8, move_with_on_off with move_mode 0) | |
| - platform: event | |
| event_type: zha_event | |
| event_data: | |
| device_id: !input dimmer_switch | |
| cluster_id: 8 | |
| command: move_with_on_off | |
| params: | |
| move_mode: 0 | |
| id: on_hold | |
| # Hold OFF (cluster 8, move with move_mode 1) | |
| - platform: event | |
| event_type: zha_event | |
| event_data: | |
| device_id: !input dimmer_switch | |
| cluster_id: 8 | |
| command: move | |
| params: | |
| move_mode: 1 | |
| id: off_hold | |
| # Button release (cluster 8, stop_with_on_off) | |
| - platform: event | |
| event_type: zha_event | |
| event_data: | |
| device_id: !input dimmer_switch | |
| cluster_id: 8 | |
| command: stop_with_on_off | |
| id: button_release | |
| action: | |
| - choose: | |
| # Single press ON: Accent first, then main if all accent are on | |
| - conditions: | |
| - condition: trigger | |
| id: on_single | |
| sequence: | |
| - choose: | |
| - conditions: | |
| - condition: template | |
| value_template: >- | |
| {{ accent_lights | select('is_state', 'off') | list | length > 0 }} | |
| sequence: | |
| - action: light.turn_on | |
| target: | |
| entity_id: "{{ accent_lights }}" | |
| default: | |
| - action: light.turn_on | |
| target: | |
| entity_id: "{{ main_lights }}" | |
| # Single press OFF: Main first, then accent if all main are off | |
| - conditions: | |
| - condition: trigger | |
| id: off_single | |
| sequence: | |
| - choose: | |
| - conditions: | |
| - condition: template | |
| value_template: >- | |
| {{ main_lights | select('is_state', 'on') | list | length > 0 }} | |
| sequence: | |
| - action: light.turn_off | |
| target: | |
| entity_id: "{{ main_lights }}" | |
| default: | |
| - action: light.turn_off | |
| target: | |
| entity_id: "{{ accent_lights }}" | |
| # Hold ON: Increase brightness of lights that are on | |
| - conditions: | |
| - condition: trigger | |
| id: on_hold | |
| sequence: | |
| - repeat: | |
| while: | |
| - condition: template | |
| value_template: "{{ repeat.index <= max_loops }}" | |
| sequence: | |
| - variables: | |
| lights_on: "{{ expand(room_lights) | selectattr('attributes.brightness', 'defined') | map(attribute='entity_id') | select('is_state', 'on') | list }}" | |
| - condition: template | |
| value_template: "{{ lights_on | length > 0 }}" | |
| - repeat: | |
| count: "{{ lights_on | length }}" | |
| sequence: | |
| - variables: | |
| current_light: "{{ lights_on[repeat.index - 1] }}" | |
| - action: light.turn_on | |
| target: | |
| entity_id: "{{ current_light }}" | |
| data: | |
| brightness_step_pct: "{{ brightness_step }}" | |
| # Wait for button release or next step | |
| - wait_for_trigger: | |
| - platform: event | |
| event_type: zha_event | |
| event_data: | |
| device_id: !input dimmer_switch | |
| cluster_id: 8 | |
| command: stop_with_on_off | |
| timeout: | |
| milliseconds: "{{ brightness_delay }}" | |
| continue_on_timeout: true | |
| # Exit if button was released | |
| - condition: template | |
| value_template: "{{ wait.trigger is defined }}" | |
| # Hold OFF: Decrease brightness of lights that are on | |
| - conditions: | |
| - condition: trigger | |
| id: off_hold | |
| sequence: | |
| - repeat: | |
| while: | |
| - condition: template | |
| value_template: "{{ repeat.index <= max_loops }}" | |
| sequence: | |
| - variables: | |
| lights_on: "{{ expand(room_lights) | selectattr('attributes.brightness', 'defined') | map(attribute='entity_id') | select('is_state', 'on') | list }}" | |
| - condition: template | |
| value_template: "{{ lights_on | length > 0 }}" | |
| - repeat: | |
| count: "{{ lights_on | length }}" | |
| sequence: | |
| - variables: | |
| current_light: "{{ lights_on[repeat.index - 1] }}" | |
| - action: light.turn_on | |
| target: | |
| entity_id: "{{ current_light }}" | |
| data: | |
| brightness_step_pct: "{{ -brightness_step }}" | |
| # Wait for button release or next step | |
| - wait_for_trigger: | |
| - platform: event | |
| event_type: zha_event | |
| event_data: | |
| device_id: !input dimmer_switch | |
| cluster_id: 8 | |
| command: stop_with_on_off | |
| timeout: | |
| milliseconds: "{{ brightness_delay }}" | |
| continue_on_timeout: true | |
| # Exit if button was released | |
| - condition: template | |
| value_template: "{{ wait.trigger is defined }}" | |
| mode: restart |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment