From b3b90bcbe791e4993cd1a29d9ed5ba7c291ff80d Mon Sep 17 00:00:00 2001 From: Matthew Grove Date: Sun, 27 Jul 2025 16:21:02 +0100 Subject: [PATCH] Add RODRET light control with optional double press actions --- ...A-Z2M_control-light-with-double-press.yaml | 656 ++++++++++++++++++ 1 file changed, 656 insertions(+) create mode 100644 ikea_E1743-E2201-E2213_ZHA-Z2M_control-light-with-double-press.yaml diff --git a/ikea_E1743-E2201-E2213_ZHA-Z2M_control-light-with-double-press.yaml b/ikea_E1743-E2201-E2213_ZHA-Z2M_control-light-with-double-press.yaml new file mode 100644 index 0000000..78e36e2 --- /dev/null +++ b/ikea_E1743-E2201-E2213_ZHA-Z2M_control-light-with-double-press.yaml @@ -0,0 +1,656 @@ +blueprint: + homeassistant: + min_version: 2024.10.0 + author: damru + domain: automation + name: Ikea's Rodret, Somrig or Tradfri 💡 Light control + description: > + ## 💡 Control a light with **IKEA RODRET** or **IKEA SOMRIG** or **IKEA TRADFRI ON/OFF** remotes + + + Only for use with [ZHA](https://www.home-assistant.io/integrations/zha/) + or Zigbee2MQTT (cf [MQTT](https://www.home-assistant.io/integrations/mqtt) + + [Z2M addon](https://www.zigbee2mqtt.io/guide/installation/03_ha_addon.html)). + + + Available controls: + + - Press **on** (Rodret, Tradfri) or **1 dot** (Somrig) to turn on the light + (Optional: set the target brightness by enabling **Force Brightness** and setting a **Brightness** value) + + - Press **off** (Rodret, Tradfri) or **2 dots** (Somrig) to turn off the light + + - Hold **on** (Rodret, Tradfri) or **1 dot** (Somrig) button to increase the brightness + + - Hold **off** (Rodret, Tradfri) or **2 dots** (Somrig) button to decrease the brightness down to 1% + + - Double press **on/off** (Rodret, Tradfri, _Optional_) **1 dot/2 dots** (Somrig) + input: + remote_devices: + name: Remotes + description: > + IKEA remote (Rodret, Somrig, Tradfri) to use. + default: [] + selector: + device: + filter: + - integration: zha + manufacturer: IKEA of Sweden + model: TRADFRI on/off switch + - integration: zha + manufacturer: IKEA of Sweden + model: RODRET Dimmer + - integration: zha + manufacturer: IKEA of Sweden + model: SOMRIG shortcut button + - integration: mqtt + manufacturer: IKEA + model: TRADFRI on/off switch + - integration: mqtt + manufacturer: IKEA + model: RODRET wireless dimmer/power switch + - integration: mqtt + manufacturer: IKEA + model: SOMRIG shortcut button + # DEPRECATED - for removal, keeping for z2m v1 backward compatibility + - integration: mqtt + manufacturer: IKEA + model: TRADFRI on/off switch (E1743) + # DEPRECATED - for removal, keeping for z2m v1 backward compatibility + - integration: mqtt + manufacturer: IKEA + model: RODRET wireless dimmer/power switch (E2201) + # DEPRECATED - for removal, keeping for z2m v1 backward compatibility + - integration: mqtt + manufacturer: IKEA + model: SOMRIG shortcut button (E2213) + multiple: true + light: + name: Light + description: Light to control + selector: + entity: + filter: + domain: light + multiple: false + brightness_section: + name: Brightness + icon: mdi:lightbulb-on-50 + collapsed: true + input: + helper_force_brightness: + name: Force brightness + description: Force the brightness to **Brightness** value when light turns on. + default: false + selector: + boolean: {} + helper_brightness: + name: Brightness + description: + Target light brightness when turning on. Requires **Force brightness** + to be enabled. + default: 50 + selector: + number: + unit_of_measurement: "%" + min: 1.0 + max: 100.0 + step: 1.0 + mode: slider + temperature_section: + name: Colour temperature + icon: mdi:lightbulb-on-50 + collapsed: true + input: + helper_max_temperature: + name: Max temperature + description: The maximum colour temperature before looping round to the minimum. + default: 450 + selector: + number: + min: 1.0 + max: 600.0 + step: 1.0 + mode: slider + helper_min_temperature: + name: Min temperature + description: The minimum colour temperature, set when the maximum has been reached and the temperature is changed. + default: 225 + selector: + number: + min: 1.0 + max: 600.0 + step: 1.0 + mode: slider + helper_temperature_change_step: + name: Temperature change step + description: + Step value to add to colour temperature for each change. + default: 75 + selector: + number: + min: 1.0 + max: 600.0 + step: 1.0 + mode: slider + helper_temperature_transition_time: + name: Temperature change transition time + description: + Number of seconds for temperature to transition over. + default: 0.5 + selector: + number: + min: 0.0 + max: 10.0 + step: 0.1 + mode: slider + on_double_press_action: + name: Double press "on / 1 dot" action + description: > + Choose action(s) to run when the **on** (Rodret, Tradfri) or **1 dot** (Somrig) button is **pressed twice**. + + **_NB for Rodret, Tradfri only_**: **Double press event (on)** must be exposed and **Double press delay** interval is used as a timeout. + default: [] + selector: + action: {} + off_double_press_action: + name: Double press "off / 2 dots" action + description: > + Choose action(s) to run when the **off** (Rodret, Tradfri) or **2 dots** (Somrig) button is **pressed twice**. + + **_NB for Rodret, Tradfri only_**: **Double press event (off)** must be exposed and **Double press delay** interval is used as a timeout. + default: [] + selector: + action: {} + rodret_tradfri_options_section: + name: Rodret, Tradfri options + icon: mdi:remote + collapsed: true + input: + on_double_press_exposed: + name: Expose virtual double press "on" event + description: > + Choose whether or not to expose the virtual **double press** event for the **on** button. + Turn this on if you are providing action(s) for the **Double press action (on / 1 dot)**. + default: false + selector: + boolean: {} + off_double_press_exposed: + name: Expose virtual double press "off" event + description: > + Choose whether or not to expose the virtual **double press** event for the **off** button. + Turn this on if you are providing an action for the **Double press action (off / 2 dots)**. + default: false + selector: + boolean: {} + helper_double_press_delay: + name: Double press delay + description: > + Max delay between the first and the second button press for the + **Double press events**. Provide a value only if you are using a double press action. + Increase this value if you notice that the double press action is not triggered + properly. + default: 250 + selector: + number: + unit_of_measurement: milliseconds + min: 100.0 + max: 5000.0 + step: 10.0 + mode: slider +mode: restart +max_exceeded: silent +triggers: + # RODRET (E2201) - TRADFRI (E1743) + - trigger: event + event_type: zha_event + event_data: + command: "on" + cluster_id: 6 + endpoint_id: 1 + id: press-on-zha-e1743-e2201 + - trigger: mqtt + topic: "+/+/action" + payload: "on" + id: press-on-z2m-e1743-e2201 + - trigger: event + event_type: zha_event + event_data: + command: "off" + cluster_id: 6 + endpoint_id: 1 + id: press-off-zha-e1743-e2201 + - trigger: mqtt + topic: "+/+/action" + payload: "off" + id: press-off-z2m-e1743-e2201 + - trigger: event + event_type: zha_event + event_data: + command: move_with_on_off + cluster_id: 8 + endpoint_id: 1 + id: hold-on-zha-e1743-e2201 + - trigger: mqtt + topic: "+/+/action" + payload: brightness_move_up + id: hold-on-z2m-e1743-e2201 + - trigger: event + event_type: zha_event + event_data: + command: move + cluster_id: 8 + endpoint_id: 1 + id: hold-off-zha-e1743-e2201 + - trigger: mqtt + topic: "+/+/action" + payload: brightness_move_down + id: hold-off-z2m-e1743-e2201 + - trigger: event + event_type: zha_event + event_data: + command: stop_with_on_off + endpoint_id: 1 + cluster_id: 8 + id: release-zha-e1743-e2201 + - trigger: mqtt + topic: "+/+/action" + payload: brightness_stop + id: release-z2m-e1743-e2201 + + # SOMRIG - E2213 + - trigger: event + event_type: zha_event + event_data: + command: short_release + endpoint_id: 1 + id: press-dots1-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 1_short_release + id: press-dots1-z2m-e2213 + - trigger: event + event_type: zha_event + event_data: + command: short_release + endpoint_id: 2 + id: press-dots2-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 2_short_release + id: press-dots2-z2m-e2213 + - trigger: event + event_type: zha_event + event_data: + command: multi_press_complete + endpoint_id: 1 + id: double-press-dots1-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 1_double_press + id: double-press-dots1-z2m-e2213 + - trigger: event + event_type: zha_event + event_data: + command: multi_press_complete + endpoint_id: 2 + id: double-press-dots2-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 2_double_press + id: double-press-dots2-z2m-e2213 + - trigger: event + event_type: zha_event + event_data: + command: long_press + endpoint_id: 1 + id: hold-dots1-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 1_long_press + id: hold-dots1-z2m-e2213 + - trigger: event + event_type: zha_event + event_data: + command: long_press + endpoint_id: 2 + id: hold-dots2-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 2_long_press + id: hold-dots2-z2m-e2213 + - trigger: event + event_type: zha_event + event_data: + command: long_release + endpoint_id: 1 + id: release-hold-dots1-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 1_long_release + id: release-hold-dots1-z2m-e2213 + - trigger: event + event_type: zha_event + event_data: + command: long_release + endpoint_id: 2 + id: release-hold-dots2-zha-e2213 + - trigger: mqtt + topic: "+/+/action" + payload: 2_long_release + id: release-hold-dots2-z2m-e2213 +variables: + helper_force_brightness: !input helper_force_brightness + helper_hold_delay: 0.1 + helper_hold_dim_step: 4 + helper_min_temperature: !input helper_min_temperature + helper_max_temperature: !input helper_max_temperature + helper_temperature_change_step: !input helper_temperature_change_step + is_mqtt: "{{ trigger.platform == 'mqtt' }}" + is_zha: "{{ trigger.platform == 'event' and trigger.event.event_type == 'zha_event' }}" + light: !input light + mqtt_topic: "{{ trigger.topic }}" + remote_devices: !input remote_devices + remote_devices_names: "{{ remote_devices | map('device_attr', 'name') | list }}" + on_double_press_exposed: !input on_double_press_exposed + off_double_press_exposed: !input off_double_press_exposed +condition: + - condition: template + value_template: >- + {{ + (trigger.event.data.device_id in remote_devices if is_zha) or + (trigger.topic.split('/')[1] in remote_devices_names if is_mqtt) + }} +actions: + - choose: + - conditions: + - condition: trigger + id: + - press-on-zha-e1743-e2201 + - press-on-z2m-e1743-e2201 + - press-dots1-zha-e2213 + - press-dots1-z2m-e2213 + sequence: + - if: + - condition: template + value_template: "{{ on_double_press_exposed }}" + then: + - choose: + - conditions: + - condition: trigger + id: + - press-on-zha-e1743-e2201 + sequence: + - wait_for_trigger: + - trigger: event + event_type: zha_event + event_data: + device_id: "{{ remote_device }}" + command: "on" + cluster_id: 6 + endpoint_id: 1 + timeout: + milliseconds: !input helper_double_press_delay + continue_on_timeout: true + - if: + - condition: template + value_template: "{{ wait.trigger.idx is defined }}" + then: !input on_double_press_action + else: + sequence: + - if: + - condition: state + entity_id: !input light + state: "on" + then: + - action: light.turn_on + data: + color_temp: "{% if state_attr(light, 'color_temp')|int >= helper_max_temperature %}{{ helper_min_temperature }}{% else %}{{ state_attr(light, 'color_temp')|int + helper_temperature_change_step }}{% endif %}" + transition: !input helper_temperature_transition_time + target: + entity_id: !input light + else: + - choose: + - conditions: "{{ helper_force_brightness }}" + sequence: + - action: light.turn_on + target: + entity_id: !input light + data: + brightness_pct: !input helper_brightness + default: + - action: light.turn_on + target: + entity_id: !input light + data: {} + - conditions: + - condition: trigger + id: + - press-on-z2m-e1743-e2201 + sequence: + - wait_for_trigger: + - trigger: mqtt + topic: "{{ mqtt_topic }}" + payload: "on" + timeout: + milliseconds: !input helper_double_press_delay + continue_on_timeout: true + - if: + - condition: template + value_template: "{{ wait.trigger.idx is defined }}" + then: !input on_double_press_action + else: + sequence: + - if: + - condition: state + entity_id: !input light + state: "on" + then: + - action: light.turn_on + data: + color_temp: "{% if state_attr(light, 'color_temp')|int >= helper_max_temperature %}{{ helper_min_temperature }}{% else %}{{ state_attr(light, 'color_temp')|int + helper_temperature_change_step }}{% endif %}" + transition: !input helper_temperature_transition_time + target: + entity_id: !input light + else: + - choose: + - conditions: "{{ helper_force_brightness }}" + sequence: + - action: light.turn_on + target: + entity_id: !input light + data: + brightness_pct: !input helper_brightness + default: + - action: light.turn_on + target: + entity_id: !input light + data: {} + default: + sequence: + - if: + - condition: state + entity_id: !input light + state: "on" + then: + - action: light.turn_on + data: + color_temp: "{% if state_attr(light, 'color_temp')|int >= helper_max_temperature %}{{ helper_min_temperature }}{% else %}{{ state_attr(light, 'color_temp')|int + helper_temperature_change_step }}{% endif %}" + transition: !input helper_temperature_transition_time + target: + entity_id: !input light + else: + - choose: + - conditions: "{{ helper_force_brightness }}" + sequence: + - action: light.turn_on + target: + entity_id: !input light + data: + brightness_pct: !input helper_brightness + default: + - action: light.turn_on + target: + entity_id: !input light + data: {} + else: + sequence: + - if: + - condition: state + entity_id: !input light + state: "on" + then: + - action: light.turn_on + data: + color_temp: "{% if state_attr(light, 'color_temp')|int >= helper_max_temperature %}{{ helper_min_temperature }}{% else %}{{ state_attr(light, 'color_temp')|int + helper_temperature_change_step }}{% endif %}" + transition: !input helper_temperature_transition_time + target: + entity_id: !input light + else: + - choose: + - conditions: "{{ helper_force_brightness }}" + sequence: + - action: light.turn_on + target: + entity_id: !input light + data: + brightness_pct: !input helper_brightness + default: + - action: light.turn_on + target: + entity_id: !input light + data: {} + - conditions: + - condition: trigger + id: + - press-off-zha-e1743-e2201 + - press-off-z2m-e1743-e2201 + - press-dots2-zha-e2213 + - press-dots2-z2m-e2213 + sequence: + - if: + - condition: template + value_template: "{{ off_double_press_exposed }}" + then: + - choose: + - conditions: + - condition: trigger + id: + - press-off-zha-e1743-e2201 + sequence: + - wait_for_trigger: + - trigger: event + event_type: zha_event + event_data: + device_id: "{{ remote_device }}" + command: "off" + cluster_id: 6 + endpoint_id: 1 + timeout: + milliseconds: !input helper_double_press_delay + continue_on_timeout: true + - if: + - condition: template + value_template: "{{ wait.trigger.idx is defined }}" + then: !input off_double_press_action + else: + - action: light.turn_off + target: + entity_id: !input light + data: {} + - conditions: + - condition: trigger + id: + - press-off-z2m-e1743-e2201 + sequence: + - wait_for_trigger: + - trigger: mqtt + topic: "{{ mqtt_topic }}" + payload: "off" + timeout: + milliseconds: !input helper_double_press_delay + continue_on_timeout: true + - if: + - condition: template + value_template: "{{ wait.trigger.idx is defined }}" + then: !input off_double_press_action + else: + - action: light.turn_off + target: + entity_id: !input light + data: {} + default: + - action: light.turn_off + target: + entity_id: !input light + data: {} + else: + - action: light.turn_off + target: + entity_id: !input light + data: {} + - conditions: + - condition: trigger + id: + - double-press-dots1-zha-e2213 + - double-press-dots1-z2m-e2213 + sequence: !input on_double_press_action + - conditions: + - condition: trigger + id: + - double-press-dots2-zha-e2213 + - double-press-dots2-z2m-e2213 + sequence: !input off_double_press_action + - conditions: + - condition: trigger + id: + - hold-on-zha-e1743-e2201 + - hold-on-z2m-e1743-e2201 + - hold-dots1-zha-e2213 + - hold-dots1-z2m-e2213 + sequence: + - repeat: + while: + - condition: trigger + id: + - hold-on-zha-e1743-e2201 + - hold-on-z2m-e1743-e2201 + - hold-dots1-zha-e2213 + - hold-dots1-z2m-e2213 + sequence: + - parallel: + - action: light.turn_on + target: + entity_id: !input light + data: + brightness_step_pct: "{{ helper_hold_dim_step }}" + transition: "{{ helper_hold_delay }}" + - delay: "{{ helper_hold_delay }}" + - conditions: + - condition: trigger + id: + - hold-off-zha-e1743-e2201 + - hold-off-z2m-e1743-e2201 + - hold-dots2-zha-e2213 + - hold-dots2-z2m-e2213 + sequence: + - variables: + brightness_pct: "{{ iif(is_state(light, 'on'), state_attr(light, 'brightness'), 0) * 100 / 255 }}" + total_iterations_to_zero: "{{ (brightness_pct / helper_hold_dim_step) | round(0, 'ceil') }}" + - repeat: + count: "{{ total_iterations_to_zero - 1 }}" + sequence: + - parallel: + - action: light.turn_on + target: + entity_id: !input light + data: + brightness_step_pct: "{{ helper_hold_dim_step | int * -1 }}" + transition: "{{ helper_hold_delay }}" + - delay: "{{ helper_hold_delay }}" + - action: light.turn_on + target: + entity_id: !input light + data: + brightness_pct: 1 + transition: "{{ helper_hold_delay }}"