Skip to content

Instantly share code, notes, and snippets.

@issmirnov
Last active April 30, 2025 08:32
Show Gist options
  • Save issmirnov/9b10a02b9ab01015cd17afb1e6c4e6da to your computer and use it in GitHub Desktop.
Save issmirnov/9b10a02b9ab01015cd17afb1e6c4e6da to your computer and use it in GitHub Desktop.
blueprint:
name: ZHA - Moes Smart Knob for lights (RGB cycle + optional double‑press)
description: >
Fork of GonzaloAlbito’s original blueprint, modified to add **hue cycling** on
press‑and‑hold and (optionally) a custom **double‑press** action while keeping
the original brightness‑dimming logic and reliability work‑arounds (repeat
loops, service_template, data_template).
• **Rotate** → brightness ±*Light step* % per encoder tick.
• **Press & hold** → every `step_color_temp` or `move_hue` event (depends on
firmware) steps the hue by ±*Hue step*°.
• **Single press** → user‑defined action.
• **Double press** *(cluster 6 → command "on")* → optional user‑defined
action.
Version 2025‑04‑29.
domain: automation
input:
remote:
name: Remote
description: Moes Knob to use
selector:
device:
integration: zha
manufacturer: _TZ3000_qja6nq5z
model: TS004F
multiple: false
light:
name: Light(s)
description: RGB lights to dim (rotate) and colour‑cycle (press & hold)
selector:
target:
entity:
domain: light
step_percent:
name: Light step
description: Brightness % change for each knob step while rotating freely
selector:
number:
mode: slider
min: 1
max: 100
unit_of_measurement: "%"
default: 20
hue_step:
name: Hue step
description: Degrees to advance around the colour‑wheel on every hue event
selector:
number:
mode: slider
min: 1
max: 60
unit_of_measurement: "°"
default: 15
single_press:
name: Single press
description: Action to run on single press
default: []
selector:
action: {}
double_press:
name: Double press (optional)
description: Action to run on double press — leave empty to ignore
default: []
selector:
action: {}
mode: restart
max_exceeded: silent
trigger:
- platform: event
event_type: zha_event
event_data:
device_id: !input remote
action:
- variables:
command: "{{ trigger.event.data.command }}"
cluster_id: "{{ trigger.event.data.cluster_id }}"
endpoint_id: "{{ trigger.event.data.endpoint_id }}"
mode: >
{% if command not in ['toggle', 'on'] %}
{{ trigger.event.data.args[0] }}
{% endif %}
steps: >
{% if command not in ['toggle', 'on'] %}
{{ (trigger.event.data.args[1] / 12.5) | int }}
{% endif %}
step_percent: !input step_percent
hue_step: !input hue_step
_target: !input light # store the target dict
ref_entity: > # first entity_id inside the target
{{ _target.entity_id if _target.entity_id is string else _target.entity_id[0] }}
current_hue: > # current hue of that entity (0‑360)
{{ (state_attr(ref_entity, 'hs_color')[0] if state_attr(ref_entity, 'hs_color') is not none else 0) }}
- choose:
# ─── Single press ───────────────────────────────────────────────────────
- conditions:
- "{{ cluster_id == 6 }}"
- "{{ endpoint_id == 1 }}"
- "{{ command == 'toggle' }}"
sequence: !input single_press
# ─── Double press (if configured) ───────────────────────────────────────
- conditions:
- "{{ cluster_id == 6 }}"
- "{{ endpoint_id == 1 }}"
- "{{ command == 'on' }}"
- "{{ double_press | length > 0 }}"
sequence: !input double_press
# ─── Rotate brightness up ───────────────────────────────────────────────
- conditions:
- "{{ cluster_id == 8 }}"
- "{{ endpoint_id == 1 }}"
- "{{ command == 'step' }}"
- "{{ mode == 'StepMode.Up' }}"
sequence:
- repeat:
while:
- condition: template
value_template: '{{ repeat.index < 2 }}'
sequence:
- service_template: light.turn_on
target: !input light
data_template:
brightness_step_pct: '{{ step_percent * steps }}'
transition: 0.5
# ─── Rotate brightness down ─────────────────────────────────────────────
- conditions:
- "{{ cluster_id == 8 }}"
- "{{ endpoint_id == 1 }}"
- "{{ command == 'step' }}"
- "{{ mode == 'StepMode.Down' }}"
sequence:
- repeat:
while:
- condition: template
value_template: '{{ repeat.index < 2 }}'
sequence:
- service_template: light.turn_on
target: !input light
data_template:
brightness_step_pct: '-{{ step_percent * steps }}'
transition: 0.5
# ─── Press & hold → cycle hue up ───────────────────────────────────────
- conditions:
- "{{ cluster_id == 768 }}"
- "{{ endpoint_id == 1 }}"
- "{{ command in ['step_color_temp', 'move_hue'] }}"
- "{{ mode == 'StepMode.Up' }}"
sequence:
- repeat:
while:
- condition: template
value_template: '{{ repeat.index < 2 }}'
sequence:
- service_template: light.turn_on
target: !input light
data_template:
hs_color:
- '{{ (current_hue + hue_step) % 360 }}'
- 100
transition: 0.1
# ─── Press & hold → cycle hue down ─────────────────────────────────────
- conditions:
- "{{ cluster_id == 768 }}"
- "{{ endpoint_id == 1 }}"
- "{{ command in ['step_color_temp', 'move_hue'] }}"
- "{{ mode == 'StepMode.Down' }}"
sequence:
- repeat:
while:
- condition: template
value_template: '{{ repeat.index < 2 }}'
sequence:
- service_template: light.turn_on
target: !input light
data_template:
hs_color:
- '{{ (current_hue - hue_step) % 360 }}'
- 100
transition: 0.1
@issmirnov
Copy link
Author

issmirnov commented Apr 29, 2025

Fork from https://gist.github.com/gonzaloalbito/3dc06702e941e08298ea9bfade731731, attempting to have the press and hold action cycle through the RGB spectrum.

Currently stable.

@gonzaloalbito
Copy link

Nice! I'll give it a try :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment