Skip to content

Instantly share code, notes, and snippets.

@issmirnov
Last active April 29, 2025 19:31
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.

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