Reliable MOES Zigbee Knob Home Assistant Kitchen Light Setup

kitchen-light-with-a-moes-zigbee-knob-home-assistant.md
title Reliable MOES Zigbee Knob Home Assistant Kitchen Light Setup
date
author VahaC
read 9 min read
category Smart home
tags #HomeAssistant #Light #SmartHome #Zigbee2MQTT
Reliable MOES Zigbee Knob Home Assistant Kitchen Light Setup

⚠️ Updated for Home Assistant 2026.3+ (March 2026). Home Assistant 2026.3 removed the deprecated mired‑based color_temp parameter (and the kelvin parameter) from the light.turn_on action, and also removed the color_temp, min_mireds, and max_mireds light entity attributes. If you built this MOES Zigbee Knob Home Assistant automation before that release, the color‑temperature steps will now fail with extra keys not allowed @ data['color_temp']. This post has been rewritten to use color_temp_kelvin, min_color_temp_kelvin, and max_color_temp_kelvin instead. Official source: Home Assistant 2026.3 — “A clean sweep” release notes.

This is a complete MOES Zigbee Knob Home Assistant setup for a kitchen light: one rotary knob, five gestures, and a single automation that handles toggle, brightness, and color temperature. The MOES Zigbee Smart Knob is a compact Zigbee rotary controller with push, double‑tap, and rotation gestures. It pairs through your Zigbee gateway (e.g., Z2M/ZHA) and exposes actions over MQTT, making it a solid fit for toggle, brightness step, and color temperature adjustments. Product page: AliExpress • MOES Zigbee Smart Knob.

In this post, I’ll walk through the full MOES Zigbee Knob Home Assistant automation that:

  • 🟢 Toggles the kitchen light with a single press
  • 🌗 Steps brightness up/down in precise percentages on rotate
  • 🌡️ Steps color temperature (Kelvin) warmer/cooler
  • 🧠 Handles edge cases (off → on, min/max boundaries) without flicker

If you’re also building smart-home controls around your kitchen, check out my Matter light sync guide and my post on dashboard strategies for Home Assistant for related ideas.


The Automation

alias: Kitchen light setting
description: ""
triggers:
  - id: light_toggle
    domain: mqtt
    device_id: cbf7dfabcf8e9f15a987456920c2a4d
    type: action
    subtype: toggle
    trigger: device
  - id: step_down
    domain: mqtt
    device_id: cbf7dfabcf8e9f15a987456920c2a4d
    type: action
    subtype: brightness_step_down
    trigger: device
  - id: step_up
    domain: mqtt
    device_id: cbf7dfabcf8e9f15a987456920c2a4d
    type: action
    subtype: brightness_step_up
    trigger: device
  - id: temp_step_down
    domain: mqtt
    device_id: cbf7dfabcf8e9f15a987456920c2a4d
    type: action
    subtype: color_temperature_step_down
    trigger: device
  - id: temp_step_up
    domain: mqtt
    device_id: cbf7dfabcf8e9f15a987456920c2a4d
    type: action
    subtype: color_temperature_step_up
    trigger: device
conditions: []
actions:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{ trigger.id == 'light_toggle' }}"
        sequence:
          - target:
              entity_id: "{{ target_light }}"
            action: light.toggle
      - conditions:
          - condition: template
            value_template: "{{ trigger.id == 'step_down' }}"
        sequence:
          - target:
              entity_id: "{{ target_light }}"
            data:
              brightness: >
                {% set step = (255 * (bright_step_pct|int) / 100) | round(0) | int %}
                {% set curr = state_attr(target_light, 'brightness') | int(0) %}
                {% set is_on = states(target_light) == 'on' %}
                {% set base = curr if (is_on and curr>0) else 0 %}
                {{ [base - step, 1] | max }}
            action: light.turn_on
      - conditions:
          - condition: template
            value_template: "{{ trigger.id == 'step_up' }}"
        sequence:
          - target:
              entity_id: "{{ target_light }}"
            data:
              brightness: >
                {% set step = (255 * (bright_step_pct|int) / 100) | round(0) | int %}
                {% set curr = state_attr(target_light, 'brightness') | int(0) %}
                {% set is_on = states(target_light) == 'on' %}
                {% set base = curr if (is_on and curr>0) else 0 %}
                {{ [base + step, 255] | min }}
            action: light.turn_on
      # NOTE: Home Assistant 2026.3 removed the mired-based 'color_temp' parameter
      # and the color_temp/min_mireds/max_mireds attributes. Use color_temp_kelvin,
      # min_color_temp_kelvin and max_color_temp_kelvin instead.
      - conditions:
          - condition: template
            value_template: "{{ trigger.id == 'temp_step_down' }}"
        sequence:
          - target:
              entity_id: "{{ target_light }}"
            data:
              color_temp_kelvin: >
                {% set current = state_attr(target_light, 'color_temp_kelvin') | int(4000) %}
                {% set min_k = state_attr(target_light, 'min_color_temp_kelvin') | int(2000) %}
                {% set step = kelvin_step | int(300) %}
                {{ [current - step, min_k] | max }}
            action: light.turn_on
      - conditions:
          - condition: template
            value_template: "{{ trigger.id == 'temp_step_up' }}"
        sequence:
          - target:
              entity_id: "{{ target_light }}"
            data:
              color_temp_kelvin: >
                {% set current = state_attr(target_light, 'color_temp_kelvin') | int(4000) %}
                {% set max_k = state_attr(target_light, 'max_color_temp_kelvin') | int(6500) %}
                {% set step = kelvin_step | int(300) %}
                {{ [current + step, max_k] | min }}
            action: light.turn_on
variables:
  target_light: light.matter_kitchen_light
  kelvin_step: 300
  bright_step_pct: 10
mode: queued
max: 20

Why This MOES Zigbee Knob Home Assistant Automation Works

  • MQTT device triggers map the knob’s gestures to five clear IDs: light_toggle, step_up, step_down, temp_step_up, temp_step_down. This keeps the action routing simple and readable. 🧭
  • Single automation handles all gestures with a choose block, avoiding duplicated state checks and keeping logic centralized. 🧩
  • Stateless brightness math: brightness uses an absolute 0–255 scale, so stepping in percent (e.g., 10%) translates into predictable increments across bulbs. 📈
  • Kelvin for CT (as of HA 2026.3): color temperature now uses Kelvin directly, since light.turn_on no longer accepts color_temp in mireds. The template reads color_temp_kelvin, min_color_temp_kelvin, and max_color_temp_kelvin straight from the entity — no unit conversion needed anymore. 🌞➡️🌙
  • Boundaries protected: both brightness and CT clamp to [min, max] so the light never errors at extremes. 🛡️

Prerequisites for This MOES Zigbee Knob Home Assistant Build

Important for Zigbee2MQTT: set your dimmer’s Operation mode to event (not command). In Zigbee2MQTT → your device → ExposesOperation mode, choose event so the knob sends click/rotate events. In command mode it tries to control groups directly and Home Assistant won’t receive the MQTT device triggers used by this automation.

  • A Zigbee gateway (Zigbee2MQTT or ZHA) that exposes knob actions as MQTT device triggers in Home Assistant.
  • A dimmable, CT‑capable light (Matter/Zigbee/Wi‑Fi) registered in HA, here: light.matter_kitchen_light. If you’re already syncing multiple Matter lights, see my Matter light sync guide.
  • Your knob’s device_id (replace cbf7dfabcf8e9f15a987456920c2a4d with yours). 🔧
  • Home Assistant 2026.3 or newer if you want to use the color‑temperature block exactly as written below (Kelvin‑based). On older versions you’d need the mired‑based color_temp parameter, which is no longer supported going forward. For a broader look at what changed around that time, see my Home Assistant 2026.4 feature roundup.

Trigger Mapping (MOES Knob → HA Actions)

These five gestures are the backbone of the MOES Zigbee Knob Home Assistant trigger mapping used above:

  • Single presstogglelight_toggle (on/off)
  • Rotate rightbrightness_step_upstep_up (brighter)
  • Rotate leftbrightness_step_downstep_down (dimmer)
  • Double‑tap / long‑press variants on some firmwares can be mapped similarly if exposed; this example focuses on the common five. 🎛️

Variables You Can Tune

variables:
  target_light: light.matter_kitchen_light   # Your kitchen light entity
  kelvin_step: 300                            # CT step size in Kelvin (smaller = finer)
  bright_step_pct: 10                         # Brightness step as percent of 255

Both of these are the only two settings you typically need to touch in this MOES Zigbee Knob Home Assistant configuration:

  • bright_step_pct: 10 → 25–26 brightness points per step. For finer control set 5.
  • kelvin_step: 300 is a reasonable starting point, but it’s not a precise equivalent of the old mired_step: 15 — Kelvin and mireds are inversely related (K = 1,000,000 / mired), so a fixed mired step does not translate into a fixed Kelvin step across the whole range. Treat 300 as a starting assumption and adjust it against your actual light’s min_color_temp_kelvin/max_color_temp_kelvin range (check these in Developer Tools → States for your light entity).

Brightness Math, Explained

{% set step = (255 * (bright_step_pct|int) / 100) | round(0) | int %}
{% set curr = state_attr(target_light, 'brightness') | int(0) %}
{% set is_on = states(target_light) == 'on' %}
{% set base = curr if (is_on and curr>0) else 0 %}

This brightness formula is reused unchanged for both step directions in the MOES Zigbee Knob Home Assistant automation:

  • Convert a percentage into the 0–255 scale.
  • Read the current brightness; if the light is off or missing a value, base is 0.
  • Decrease branch clamps with max([... , 1]) to avoid 0 (some bulbs treat 0 as off).
  • Increase branch clamps with min([... , 255]) to prevent overflow.

Color Temperature in Kelvin (Updated for HA 2026.3)

{% set current = state_attr(target_light, 'color_temp_kelvin') | int(4000) %}
{% set min_k = state_attr(target_light, 'min_color_temp_kelvin') | int(2000) %}
{% set max_k = state_attr(target_light, 'max_color_temp_kelvin') | int(6500) %}
{% set step = kelvin_step | int(300) %}
  • Older versions of this automation read the color_temp attribute in mireds, with a fallback conversion from Kelvin. As of Home Assistant 2026.3, the color_temp, min_mireds, and max_mireds attributes no longer exist on light entities, and light.turn_on rejects the color_temp and kelvin parameters outright — the call fails with extra keys not allowed @ data['color_temp']. Source: Home Assistant 2026.3 release notes.
  • The fix is to read and write color_temp_kelvin directly, and clamp against the entity’s own min_color_temp_kelvin / max_color_temp_kelvin — no manual mired↔Kelvin conversion needed anymore.
  • temp_step_up makes the light cooler (higher Kelvin), temp_step_down makes it warmer (lower Kelvin) — same directional behavior as before, just expressed in Kelvin instead of mireds. 🌤️

Mode & Concurrency

mode: queued
max: 20
  • queued ensures quick successive rotations don’t cancel each other. The queue caps at 20 to avoid backlog when you spin the knob like a DJ. 🎚️ This queuing behavior is what keeps the MOES Zigbee Knob Home Assistant automation responsive under rapid input.

Troubleshooting This MOES Zigbee Knob Home Assistant Automation 🛠️

  • Nothing happens: confirm the knob’s device_id and that actions appear in Developer Tools → Events or Z2M logs.
  • Jittery brightness: reduce bright_step_pct to 5 or 3.
  • extra keys not allowed @ data['color_temp']: you’re on Home Assistant 2026.3+ and still have an old, mired‑based version of this automation. Update it to use color_temp_kelvin as shown above.
  • CT doesn’t change: verify your light supports color_temp_kelvin and check min_color_temp_kelvin / max_color_temp_kelvin in the entity’s attributes (in Developer Tools → States).
  • Latency: ensure MQTT broker and Zigbee coordinator are on stable power and not CPU‑throttled.

Extend It ✨

These ideas build on the same MOES Zigbee Knob Home Assistant foundation described above:

  • Map double‑tap to “max brightness” or to a scene.
  • Add a hold gesture to toggle between warm/cool presets.
  • Include a helper (input_number) to adjust bright_step_pct at runtime from the dashboard. For dashboard layout ideas, see my Home Assistant custom dashboard strategies post, or my ESP32-4848S040 media controller build if you want a dedicated physical control panel instead of a knob.

Credits

This MOES Zigbee Knob Home Assistant setup keeps working the same way it always did for toggling and dimming — the only real change is how color temperature is expressed under the hood. Happy automating! 🏡💡

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.