Moes Smart Knob Lights Control

I figured out that my dimmable lamps needed to be reconnected as they were not working properly.

I reduced the code to step the brightness by 5% each step, no matter how fast you spin the knob and also included push and rotate to step by 20%.

It may be worth looking into colour changing with push and rotate, but I don’t have RGB lamps at this time.

Nice blueprint @seamus65 ! I would like to get this working with color temperature since the latest zha quirks update made it possible to detect hold-and-rotate for my device.
Unfortunatly there isnt an “color_step” function like with brightness…

Does anyone have any clue how to accomplish this?

Hi everyone,

I’ve been busy with this blueprint merged with some of my other Tuya blueprints and added the color temperature integration as well as switching modes:

  • Color temp: Press and rotate, simple as that :slight_smile:
  • Event/Scene mode: Press button 3 times (fast) and it will switch to event mode.
  • Speed: I also took the “speed” param in dimmer mode into account for the transition speed.

Keep in mind that this blueprint contains input for both schene (event) and dimmer (command) mode.
This way you can switch modes and use both in one automation!

At the moment I’ve kept the automation mode as restart, however I’m unsure whether this is the best mode. parallel might build up quite fast and single or queued isn’t useful for dimming.

More info about the different modes: [Device Support Request] TS004F Tuya Smart Knob · Issue #1322 · zigpy/zha-device-handlers · GitHub

blueprint:

  name: ZHA - Tuya - TS004F Rotating Knob - Custom Actions

  description: >-
    This automation adds triggers for all actions of the rotating knob remote
    form AliExpress brands like Moes, Girier etc.

  domain: automation

  input:
    remote:
      name: Tuya - TS004F Rotating Knob
      description: Select the remote control you wish to use.
      selector:
        device:
          integration: zha
          manufacturer: _TZ3000_4fjiwweb
          model: TS004F
    light:
      name: Light (Command/Dimmer mode)
      selector:
        target:
          entity:
            domain: light
    toggle:
      name: Toggle (Command/Dimmer mode)
      selector:
        action:
      default: []
    press_short:
      name: Short Press (Event/Scene mode)
      selector:
        action:
      default: []
    press_double:
      name: Double Press (Event/Scene mode)
      selector:
        action:
      default: []
    press_long:
      name: Long Press (Event/Scene mode)
      selector:
        action:
      default: []
    rotate_left:
      name: Rotate Left (Event/Scene mode)
      selector:
        action:
      default: []
    rotate_right:
      name: Rotate Right (Event/Scene mode)
      selector:
        action:
      default: []

mode: restart
max_exceeded: silent

trigger:
  - platform: event
    event_type: zha_event
    event_data:
      device_id: !input remote

action:
  - variables:
      light: !input light
      command: "{{ trigger.event.data.command }}"
      cluster_id: "{{ trigger.event.data.cluster_id }}"
      endpoint_id: "{{ trigger.event.data.endpoint_id }}"
      args: "{{ trigger.event.data.args }}"
      #direction: "{% if trigger.event.data.args[0] %} {{ trigger.event.data.args[0]|int(0) }} {% endif %}"
      direction: "{% if trigger.event.data.args[0] == 0 %} 0 {% elif trigger.event.data.args[0] == 1 %} 1 {% elif trigger.event.data.args[0] == 3 %} 3 {% endif %}"
      value: "{% if trigger.event.data.args[1] %} {{ trigger.event.data.args[1] / 2 }} {% endif %}"
      speed: "{% if trigger.event.data.args[2] == 1 %} 0.5 {% else %} 0 {% endif %}"

  - choose:

    # Command Mode
    - conditions:
        - "{{ command == 'toggle' }}"
        - "{{ cluster_id == 6 }}"
        - "{{ endpoint_id == 1 }}"
      sequence: !input toggle
    - conditions:
        - "{{ command == 'step' }}"
        - "{{ cluster_id == 8 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 0 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  brightness_step_pct: "{{ value }}"
                  transition: "{{ speed }}"
    - conditions:
        - "{{ command == 'step' }}"
        - "{{ cluster_id == 8 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 1 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  brightness_step_pct: "{{ - value }}"
                  transition: "{{ speed }}"
    - conditions:
        - "{{ command == 'step_color_temp' }}"
        - "{{ cluster_id == 768 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 1 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  color_temp: "{{ state_attr( light.entity_id, 'color_temp') + value }}"
                  transition: "{{ speed }}"
    - conditions:
        - "{{ command == 'step_color_temp' }}"
        - "{{ cluster_id == 768 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 3 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  color_temp: "{{ state_attr( light.entity_id, 'color_temp' ) - value }}"
                  transition: "{{ speed }}"

    # Short Press
    - conditions:
        - "{{ command == 'remote_button_short_press' }}"
      sequence: !input press_short

    # Double Press
    - conditions:
        - "{{ command == 'remote_button_double_press' }}"
      sequence: !input press_double

    # Long Press
    - conditions:
        - "{{ command == 'remote_button_long_press' }}"
      sequence: !input press_long

    # Rotate Left
    - conditions:
        - "{{ command == 'left' }}"
      sequence: !input rotate_left

    # Rotate Right
    - conditions:
        - "{{ command == 'right' }}"
      sequence: !input rotate_right

Let me know your thoughts!

1 Like

Modified it even more to also support color move!

When pressing and holding the button (in Command/Dimmer) mode it will switch to colors and simply loop through the available colors until you release.

One issue I did notice however is that the stop command stop_move_step isn’t always send for some reason, not sure why yet.
Therefore I’ve limited to color op to 24 times (full circle).

Any idea or comments very welcome!

blueprint:

  name: ZHA - Tuya - TS004F Rotating Knob - Custom Actions

  description: >-
    This automation adds triggers for all actions of the rotating knob remote
    form AliExpress brands like Moes, Girier etc.

  domain: automation

  input:
    remote:
      name: Tuya - TS004F Rotating Knob
      description: Select the remote control you wish to use.
      selector:
        device:
          integration: zha
          manufacturer: _TZ3000_4fjiwweb
          model: TS004F
    light:
      name: Light (Command/Dimmer mode)
      selector:
        target:
          entity:
            domain: light
    toggle:
      name: Toggle (Command/Dimmer mode)
      selector:
        action:
      default: []
    press_short:
      name: Short Press (Event/Scene mode)
      selector:
        action:
      default: []
    press_double:
      name: Double Press (Event/Scene mode)
      selector:
        action:
      default: []
    press_long:
      name: Long Press (Event/Scene mode)
      selector:
        action:
      default: []
    rotate_left:
      name: Rotate Left (Event/Scene mode)
      selector:
        action:
      default: []
    rotate_right:
      name: Rotate Right (Event/Scene mode)
      selector:
        action:
      default: []

mode: restart
max_exceeded: silent

trigger:
  - platform: event
    event_type: zha_event
    event_data:
      device_id: !input remote

action:
  - variables:
      light: !input light
      command: "{{ trigger.event.data.command }}"
      cluster_id: "{{ trigger.event.data.cluster_id }}"
      endpoint_id: "{{ trigger.event.data.endpoint_id }}"
      args: "{{ trigger.event.data.args }}"
      #direction: "{% if trigger.event.data.args[0] %} {{ trigger.event.data.args[0]|int(0) }} {% endif %}"
      direction: "{% if trigger.event.data.args[0] == 0 %} 0 {% elif trigger.event.data.args[0] == 1 %} 1 {% elif trigger.event.data.args[0] == 3 %} 3 {% endif %}"
      value: "{% if trigger.event.data.args[1] %} {{ trigger.event.data.args[1] / 2 }} {% endif %}"
      speed: "{% if trigger.event.data.args[2] == 1 %} 0.5 {% else %} 0 {% endif %}"

  - choose:

    # Command Mode
    - conditions:
        - "{{ command == 'toggle' }}"
        - "{{ cluster_id == 6 }}"
        - "{{ endpoint_id == 1 }}"
      sequence: !input toggle
    - conditions:
        - "{{ command == 'step' }}"
        - "{{ cluster_id == 8 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 0 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  brightness_step_pct: "{{ value }}"
                  transition: "{{ speed }}"
    - conditions:
        - "{{ command == 'step' }}"
        - "{{ cluster_id == 8 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 1 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  brightness_step_pct: "{{ - value }}"
                  transition: "{{ speed }}"
    - conditions:
        - "{{ command == 'step_color_temp' }}"
        - "{{ cluster_id == 768 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 1 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  color_temp: "{{ ( state_attr( light.entity_id, 'color_temp' ) or 300 ) + value }}"
                  transition: "{{ speed }}"
    - conditions:
        - "{{ command == 'step_color_temp' }}"
        - "{{ cluster_id == 768 }}"
        - "{{ endpoint_id == 1 }}"
        - "{{ direction == 3 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 2 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  color_temp: "{{ ( state_attr( light.entity_id, 'color_temp' ) or 300 ) - value }}"
                  transition: "{{ speed }}"
    - conditions:
        - "{{ command == 'move_hue' }}"
        - "{{ cluster_id == 768 }}"
        - "{{ endpoint_id == 1 }}"
      sequence:
        - repeat:
            while:
              - condition: template
                value_template: "{{ repeat.index < 24 }}"
            sequence:
              - service_template: light.turn_on
                target: !input light
                data_template:
                  hs_color:
                    - "{{ ( value + (state_attr( light.entity_id , 'hs_color' )[0] or 0)) % 360 }}"
                    - 100
                  transition: 0.5
              - delay:
                  hours: 0
                  minutes: 0
                  seconds: 1
                  milliseconds: 0
    - conditions:
        - "{{ command == 'stop_move_step' }}"
        - "{{ cluster_id == 768 }}"
        - "{{ endpoint_id == 1 }}"
      sequence:

    # Short Press
    - conditions:
        - "{{ command == 'remote_button_short_press' }}"
      sequence: !input press_short

    # Double Press
    - conditions:
        - "{{ command == 'remote_button_double_press' }}"
      sequence: !input press_double

    # Long Press
    - conditions:
        - "{{ command == 'remote_button_long_press' }}"
      sequence: !input press_long

    # Rotate Left
    - conditions:
        - "{{ command == 'left' }}"
      sequence: !input rotate_left

    # Rotate Right
    - conditions:
        - "{{ command == 'right' }}"
      sequence: !input rotate_right

Improved it even more!
You can now set your own automation mode to your preference.

See link for full blueprint:

1 Like

This works really well. I have a sputnik light with 10 zigbee white temp changing + dimmable bulbs that I have it paired to. Thanks for expanding the functionality now that the new quirks are available.

For scenes I created I input select helper (drop down and added the scenes) and added all the scenes

I then set the push and rotate right to this

the important part is the bottom

service: scene.turn_on
target:
  entity_id: scene.{{ states.input_select.aj_room_scene.state }}

hey there

i found your blueprint - looks awesome so far.
sadly i cant add my knob.
i guess its because they have a different manufacturer number:

yours: _TZ3000_4fjiwweb
mine: _TZ3000_ixla93vd

so i cant select my knob into your blueprint :frowning:
is there a way do add it?

thank you in advance

I just checked and as far as I can see I can only add one manufacturer name.
Unfortunately the model name is also used for a 4 button scene remote (totally different device…)

You can just remove the manufacturer line or change it if you want but I’m not sure what to do here to make this blueprint compatible without enabling it for non-supported devices.

thank you for your FAST response :slight_smile:

hm… since i have ZERO skills in creating blueprints, i can only guess…
(if you could show me how to edit/create a blueprint, i could test it on my own…)
is it possible to add a whole second input device instead of only adding a second line of code?
something like this?

input:
    remote:
      name: Tuya - TS004F Rotating Knob
      description: Select the remote control you wish to use.
      selector:
        device:
          integration: zha
          manufacturer: _TZ3000_ixla93vd
          model: TS004F

    remote:
      name: Tuya - TS004F Rotating Knob
      description: Select the remote control you wish to use.
      selector:
        device:
          integration: zha
          manufacturer: _TZ3000_4fjiwweb
          model: TS004F

[EDIT]
i’ve managed to modify your blueprint lokally in my HA with Studio Code Server = file editor.
apparently you’re right: there only can be set only ONE device type = one manufacturer.
maybe there is a way to put placeholders in the manufacturer name?
so HA would accept every device, that begins with “TZ3000
i tested “_TZ3000*” but wasnt successfull.
so i had to create my own with my own ID
alternatively we deactivate the manufacturer filter.
pro: compatible with all variants of the knob
con: allows 4-way switches to be selected.
→ BUT if you mention it in the description, its…okay…i guess?

besides all that:
your blueprint is missing many features to select from.
do you have plans to add them?
can i help you in any way? (even as a noob ^^)

Great work @jory ! Two things Ive noticed:

  • First i got Error: Error rendering data template: UndefinedError: 'dict object' has no attribute 'entity_id'. Reason was using an device instead of entity ID (blueprint UI made it possible to select devices, dont know if its possible to fix this / disable selecting devices…)

  • After switching over to an entity, I am able to change brightness in command/dimmer mode. Changing color doesnt though. When holding and rotating I get errors like Error: Error rendering data template: AttributeError: 'list' object has no attribute 'lower'.

    It looks like its caused here:

    data_template:
    color_temp: '{{ ( state_attr( light.entity_id, ''color_temp'' ) or 300 ) + value }}'
    transition: '{{ speed }}'
    

    …but unfortunately I cant find out why… Can you help with this?

No idea why the UI let you choose devices as the selector I’ve used clearly filters on entities in the “light” domain: https://github.com/JoryHogeveen/HomeAssistantConfig/blob/c97016bee95cb13a7437087b994665fe609873cf/blueprints/automation/tuya/tuya-TS004F-knob.yaml#L47-L52

As for the second error, I don’t get this one as I do not use the lower attribute anywhere.
I also checked the actual state values and color_temp is an integer, not a list (like hs_color).
Do you have more info on this? Does your light entity support hs_color? Please check the available state attributes in developer tools (light must be on).

Thanks for the reply. I cant replicate it right now because of some other issues Im having. But i suspect its due to me using all my living room lights, including onces not supporting color or only white spectrum.

Another TS004F on a seperate room with only white spectrum tradfri bulbs is working correctly.

Is the dimming smooth ? Is there a zigbee2mqtt variant that uses command.

I’m considering buying the Moes Knob. Is the dimming smooth?

I’ve been trying the Moes Knob for a couple weeks with Zigbee2MQTT. It is replacing a Lutron dimmer. While I will rate the Moes dimmer higher than the Lutron offering, neither are anywhere near the function or form of an old school analog dimmer knob. This is an adventure in frustration!

Directly to your question about ‘smoothness’ of the dimming of the Moes. So far, I would not call it smooth. That said, this is a ‘function’ of the function you have between the rotation messages coming in and you light devices ‘step control/ability’. I think it is possible to smooth control with both, there needs to be a maths function in between the dimming messages and light brightness or color steps. I think it needs to be a non-linear function, both on speed of ‘twist’ and level position (for brightness some type of log function to match our different perception of light levels at the dim and bright ends). I say, I think it is possible, because I tested the Lutron device with a Hue bulb and Hue hub ( am not sure if the dimmer was talking directly to the bulb or via the hub ) and the experience of operation of the Lutron device and light level perception in this scenario was much smoother.

On the physical aspect of the two dimmers, the Moes has slight ‘bumps’ that you can physically feel as you rotate, the Lutron does not. I am not sure which gives the better ‘feel’ and control. Back to the old school dimmer, these were smooth moving. However the data coming out of the Lutron is a nightmare. Both devices send out too much extraneous signal quality and battery level messages during device operation, I think these make interpreting the level movement messages harder. These status messages should only be sent when the device has been idle for a period IMHO. The MOES dimmer message stream is easier to work with from my experience so far.

Back on the physical aspect of both, the Moes ‘sticks’ out from the wall plate about 35% more than the Lutron, I am not sure that is good. And the Moes needs a better (read stronger) connection, it is magnetic and with the device sticking out as much as it does, it is somewhat easy to knock off the wall plate. On the other side, you really have to pull to get the Lutron off (only reason to take them off IMHO is to change battery), and you almost feel like you are going to break the Lutron.

Another problem for both is that there needs to be a better way to distinguish between a click and a turn. It is too easy to ‘click and slightly turn’ both devices when you are just trying to click. Maybe there is a filter of some type that can be applied to the message stream to tune this sensitivity.

While the set of messages and format of them that comes from the Moes is a big improvement over the Lutron. However, the design of the messages that come from both is odd. The Moes has two distinct modes, and generates different set of messages in each. And it odd how they are bucketed. For example you can only get a ‘double click’ message in one of the modes, that function does not seem to overlap with any function in the other mode and yet not available. And to make it more difficult on the ‘significant other acceptance factor’, if you ‘triple click’ the Moes, it flips between the two modes. And now all you messages are different, so you need to check for this mode change or the significant other will be clicking and twisting to no avail. And since the Moes is easy to remove from the wall and makes a very solid ‘throwable weapon’, I can see danger ahead :wink: .

And my final comparison between, with a plus for the Lutron and minus for the Moes, they both have LED’s that light for a moment when you click or move. The Lutron has a white LED on the front of the ring that is visible while using. The Moes has a green LED on the back side of the unit that is covered by the magnet plate that holds it to the wall, WTF? End of rant, I am going to get out my fidget spinner now… Good hunting, hope you find a good solution.

1 Like

This is a good overview and I previously used an automation for this device but moved it to be directly bound to a fixture with all zigbee CCT bulbs and its much better in every way. It really seems to be designed around zigbee binding.

Yes there is something that the zigbee direct binding is doing correctly. I hope there is a way to duplicated it outside of 100% zigbee solution as I have wifi controlled lighting fixtures that are ‘loved’…

With ZigBee binding, does it matter what brand it is bound to?

Brand no but that doesn’t mean every device will support binding or may not support all the functionality.

Mine is controlling 10 Ecosmart white adjustable LEDs in a sputnik style light. They dim and adjust perfectly in sync unlike light groups in HA which can have slight delays with this many bulbs. The press and rotate adjusts color temperature also.

Innovelli has some dimming zigbee wall switches coming out soon with binding support, scenes, rocker/paddle style for more traditional use cases on a wall also.