⏲️ Z2M Knob — Gesture Action Controller (Moes ZG-101ZD & similar AliExpress-sold knobs) with filter of false events

:wave: Zigbee2MQTT rotary knobs expose only raw MQTT events, which makes flexible and reusable configuration in Home Assistant unnecessarily complex.
I built a blueprint that turns those low-level events into configurable gestures via the UI and reliably filters noisy “tail” events, and I’m happy enough with the result to share it with the community.

Assign your own actions to Zigbee2MQTT rotary-knob gestures in Home Assistant. Supports Command/Event modes and includes noise filtering for false “tail” events.

  • Works with many Zigbee2MQTT rotary knobs (brands such as Moes, Girier, and others — mostly AliExpress-sold models)
  • Bind gestures to any HA actions or scripts, with optional helper parameters (gesture, step_size, rate, etc.)
  • Supports both Command and Event operation modes (typically switched using a triple-click on most knobs)
  • Noise filtering for accidental “tail” events (e.g., unwanted rotation after hold+rotate, or a single click triggered after rotation)
  • Allows visual customization of native low-level event mappings if your knob uses different payload values
  • Supports configuring automation mode and maximum concurrent runs
  • Debug output available via notifications or logs

Core idea of this blueprint — assign actions to gestures instead of handling raw MQTT events.

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

:open_book: Please, check official documentation, a lot of usefull details here

:framed_picture: Some additional screenshots:


2 Likes

1.0.1 - Hook script

  • Added selector for hook script: This script will start on each gesture and receive all availible variables
  • Added knob_id variable

:puzzle_piece: Hook script

You can select one script that will be triggered on each gesture and will receive all variables:

  • gesture: single | double | hold | hold_release | rotate_left | rotate_right | hold_rotate_left | hold_rotate_right | mode_change | unknown
  • step_size: action_step_size from payload
  • rate: action_rate from payload
  • operation_mode: operation_mode from payload
  • native_event: action from payload
  • topic: MQTT topic of the message
  • knob_id: Id of your knob (without “zigbee2mqtt/”)
  • raw: raw MQTT payload (string)
  • payload_json: parsed MQTT payload (dict)
1 Like

I’ve exactly the same tuya knob and have installed/followed your documentation but have a couple of questions in regards to setting up for controlling a group of rgb downlights in a room:

  • Can you supply an example automation showing use of the blueprint and configurations?
  • What is the purpose between command/event mode? Do you need to specify actions on both?

Cheers

Chris

Hi, chrisav! Welcome to community :slight_smile:

  1. Main idea for this blueprint is using it in scripts, it is base for making your solutions and also tested noise filtration. Later I will show examples and maybe new updated set of blueprints that used for my needs.
  2. Command/Event mode is feature of moes knob. They made it on hardware level - when you tripple press the knob you got mode switch and from this moment the same gestures will called another way. For example in event mode you will got “rotate_right” event, in command mode you will got “brightness_step_up”. My blueprint normalizes this and your final script will always got “rotate_right” gesture.
    About your question - you can use only hook script and not specify actions at all.
1 Like

Thanks Roman.

I get the script usage but having trouble getting the dimming, and even the on/off working consistently. Given you have the same hardware device I just wanted to see how you have implemented all of the blueprint functions into home assistant actions.

Quick sample:

alias: Lustralev — gesture control
mode: single
fields:
  gesture:
    description: rotate_right | rotate_left | single
    example: rotate_right
sequence:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ gesture == 'rotate_right' }}"
        sequence:
          - target:
              entity_id: light.lustralevb1
            data:
              brightness_step: 30
            action: light.turn_on
      - conditions:
          - condition: template
            value_template: "{{ gesture == 'rotate_left' }}"
        sequence:
          - target:
              entity_id: light.lustralevb1
            data:
              brightness_step: -30
            action: light.turn_on
      - conditions:
          - condition: template
            value_template: "{{ gesture == 'single' }}"
        sequence:
          - target:
              entity_id: light.lustralevb1
            action: light.toggle
description: ""

I must be doing something wrong. I just created a automation script from the blueprint so mine looks nothing like this?

description: ""
use_blueprint:
  path: LanKing/z2m-knobs-gesture-controller.yaml
  input:
    base_topic: zigbee2mqtt/BR Light Controller
    ev_single_action: []
    cmd_single_action:
      - action: light.toggle
        metadata: {}
        target:
          entity_id: light.ln_lights
        data: {}
    cmd_rotate_right_action:
      - condition: state
        state:
          - "on"
        entity_id: light.ln_lights
      - action: light.turn_on
        metadata: {}
        target:
          entity_id: light.ln_lights
        data:
          brightness_step_pct: 10
    cmd_rotate_left_action:
      - condition: state
        state:
          - "on"
        entity_id: light.ln_lights
      - action: light.turn_on
        metadata: {}
        target:
          entity_id: light.ln_lights
        data:
          brightness_step_pct: -10
    cmd_hold_rotate_left:
      - condition: state
        state:
          - "on"
        entity_id: light.ln_lights
      - action: light.turn_on
        metadata: {}
        target:
          entity_id: light.ln_lights
        data: {}
    debug_mode: disabled
    automation_mode: restart

Dear Chris, give me some time, I think I will answer during 2 days - currently in trip.

Main idea of this blueprint is routing. I did not added concrete actions in it because:

  1. In this case it will have more than one responsibility.
  2. It will become very big due to additional functionality.
  3. If you for example manage your lights and want to manage it via knobs and also physical switches, you need to repeat logics in different automations.

Instead of this you have one router and one script with logics for concrete light devices. You add your light script to router and got ability to manage it via knob.

How to setup:

  1. Create your ligics script: Settings → Automations and scenes → Scripts → Create script → Create new script → ⋮ → Edit in YAML
    You can use my raw sample that I gave you earlier, just change light device to yours.
  2. Setup blueprint (I think you already had done this, I mean change mqtt topic by adding your device friendly name). And choose your new script from previous step as hook script.

Also you can add your device without additional scripts if you bind it to events. E.g. single click - light turn on. But as I understand this does not works for you? Can you please turn on debug notification and check that you got events from knob?

Sorry, I just re-read your script. Let’s start from enabling debug notification and check that you got events from your knob

Ok. Now I understand what you have done. You utilise the hook script rather than direct actions in the automation script. Not sure of the operational difference but I will give that a go.

In regards to how I currently have it setup though, it’s not that it didn’t work at all, it was just hit and miss - unreliable. The dimming was janky and even the on/off action I would need to press the button multiple times for it to work.

How do you have your automation/blueprint setup for this hook script? Meaning the mode - single, restart, queued etc. ?

Thank you for understanding, but I think I confused you. Maybe for your scenario you don 't need additional hook script and actions are enough. Also you need queue mode. OR: you can use hook script and use not only gesture but also step_size as multiplier to make results of rotation more predictable. But please keep in mind that this parameter not always exist, so you need to use something like brightness*1*step_size

this looks good but I am getting

Message malformed: invalid template (TemplateAssertionError: No filter named ‘combine’.) for dictionary value @ data[‘variables’][‘_bindings’]

error trying to save automation. any ideas what I am doing wrong?

Hi! You imported blueprint via button on the topic message and when you save you got this message, right?

that is correct

Problem is that you have older version of HA. I updated the code to support your version. Please, try now. Maybe if it will not works you will need to re-import blueprint again. Let me know if it helps

First of all, tnx for the script, most is working just perfect. I’m just missing one option. It would be nice to be able to change color temp of a light incrementally with x % steps, just like it’s possible for the brightness. Is this somehow possible?

1 Like

Thank you so much for this blueprint!

Both the ZG101zd and your blueprint Worked “out of the box”
Think im going to buy some more dimmers/colourwheels/volume/curtain-buttons :grin::sunglasses:

Just a raw idea : i think you could make a helper variable that you increase and decrease.
And the different values correspond to a colour of the Rainbow?

I get a regular “fault message” of the status change of the button changing from scene to event - even if I do not even touch it. it does not matter in its function. can I just suppress this?