From 490d60adc01448f21c62e662a691a054c98f88bd Mon Sep 17 00:00:00 2001 From: Matthew Grove Date: Fri, 2 Oct 2026 23:19:42 +0100 Subject: [PATCH] Allow small rotations to trigger brightness changes with H2 EU dimmer --- aqara-h2-eu-dimmer-z2m-light-control.yaml | 53 +++++++++++++++-------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/aqara-h2-eu-dimmer-z2m-light-control.yaml b/aqara-h2-eu-dimmer-z2m-light-control.yaml index d3c0e08..be36494 100644 --- a/aqara-h2-eu-dimmer-z2m-light-control.yaml +++ b/aqara-h2-eu-dimmer-z2m-light-control.yaml @@ -44,7 +44,7 @@ blueprint: rotation_deadzone: name: Rotation Deadzone (Anti-knock) - description: The minimum rotation angle (in degrees) required to trigger a dimming action. Increase this if you accidentally dim the lights when clicking the knob. + description: The rotation angle below which the blueprint briefly waits to determine whether the event was actually a single click. default: 20 selector: number: @@ -126,11 +126,8 @@ action: payload: "{{ trigger.payload_json if trigger.payload_json is defined else {} }}" raw_action_type: "{{ payload.action | default('') }}" - # Time since the previous MQTT event triggered this automation. - # Genuine stop_rotating events immediately follow rotation events. - # The H2 bug emits a stray stop_rotating after the device has been idle. - # Null/missing action packets are filtered at the MQTT trigger above, - # so only genuine action events affect this timer. + # Time since the previous real MQTT action event. + # Null/missing action packets are filtered at the trigger above. idle_seconds: > {{ as_timestamp(now()) - as_timestamp( @@ -211,9 +208,9 @@ action: value_template: "{{ action_type == 'rotation' }}" sequence: - choose: - # A click can occasionally appear as a small rotation followed - # immediately by stop_rotating. Only treat it as a single press - # if the stop_rotating packet actually follows. + # Small rotations may actually be a misreported single click. + # Wait briefly for the stop_rotating packet that accompanies + # the H2's erroneous rotation -> stop_rotating click sequence. - conditions: - condition: template value_template: "{{ (raw_angle | abs) < (deadzone | float(0)) }}" @@ -224,24 +221,42 @@ action: payload: "stop_rotating" value_template: "{{ value_json.action | default('') }}" timeout: - milliseconds: 500 - continue_on_timeout: false + milliseconds: 300 + continue_on_timeout: true - choose: + # stop_rotating arrived within the click window: + # treat the small rotation as a single press. - conditions: - condition: template - value_template: "{{ enable_toggle }}" + value_template: "{{ wait.completed }}" sequence: - - service: light.toggle - target: !input target_light + - choose: + - conditions: + - condition: template + value_template: "{{ enable_toggle }}" + sequence: + - service: light.toggle + target: !input target_light - - choose: - - conditions: [] - sequence: !input single_press_action + - choose: + - conditions: [] + sequence: !input single_press_action - # Normal rotation above the configured deadzone. + # No stop_rotating within the click window: + # this was a genuine small rotation, so apply it. + default: + - condition: template + value_template: "{{ scaled_step != 0 }}" + - service: light.turn_on + target: !input target_light + data: + brightness_step_pct: "{{ scaled_step }}" + transition: !input dim_transition + + # Rotation exceeds the deadzone, so it is unambiguously a + # genuine rotation and can be processed immediately. default: - # Only fire the turn_on service if there was a registrable angle change - condition: template value_template: "{{ scaled_step != 0 }}" - service: light.turn_on