Skip to content

Instantly share code, notes, and snippets.

@spotshare-nick
Created June 12, 2026 01:36
Show Gist options
  • Select an option

  • Save spotshare-nick/4149761d1f19ffed5d1c952da48a2a3c to your computer and use it in GitHub Desktop.

Select an option

Save spotshare-nick/4149761d1f19ffed5d1c952da48a2a3c to your computer and use it in GitHub Desktop.
Home Assistant blueprint: Inovelli VZM31-SN Color Cycle (cycle an editable RGB/Kelvin palette from a button gesture; recolours the LED bar to match)
blueprint:
name: VZM31-SN Color Cycle
description: >
Cycle a light through an editable colour palette (RGB or colour-temperature)
from an Inovelli VZM31-SN button gesture, and recolour the switch LED bar to
match. Attach the cycle to ANY gesture (config press, double-tap, …) — the
action is decoupled from the button. Per-switch palette + index helper make it
reusable across switches/people.
domain: automation
input:
switch_device:
name: Inovelli switch
description: The VZM31-SN whose button fires the cycle.
selector:
device:
integration: zha
manufacturer: Inovelli
model: VZM31-SN
gesture:
name: Trigger gesture
description: >
Which gesture advances the colour. (Invert OFF -> Up = button_2,
Down = button_1, Config = button_3.)
default: button_3_press
selector:
select:
options:
- {label: "Config — 1x", value: button_3_press}
- {label: "Config — 2x", value: button_3_double}
- {label: "Config — 3x", value: button_3_triple}
- {label: "Up — 2x", value: button_2_double}
- {label: "Up — 3x", value: button_2_triple}
- {label: "Down — 2x", value: button_1_double}
- {label: "Down — 3x", value: button_1_triple}
target_light:
name: Target light
description: The bulb(s) to colour.
selector:
entity:
filter:
domain: light
led_color_entity:
name: Switch LED colour entity
description: >
The switch's "Default all LED on color" number (0-255 hue) — recoloured to
match each palette entry's led_hue.
selector:
entity:
filter:
domain: number
index_helper:
name: Index helper (input_number)
description: Remembers the current palette position for this switch.
selector:
entity:
filter:
domain: input_number
palette:
name: Colour palette
description: >
Ordered list cycled on each gesture. Each item: a name and EITHER
rgb_color [r,g,b] OR color_temp_kelvin N, plus led_hue (0-255; 255 = white)
for the LED bar. Edit freely.
default:
- {name: Warm White, color_temp_kelvin: 2700, led_hue: 255}
- {name: Red, rgb_color: [255, 0, 0], led_hue: 0}
- {name: Green, rgb_color: [0, 255, 60], led_hue: 85}
- {name: Blue, rgb_color: [0, 80, 255], led_hue: 170}
selector:
object: {}
mode: restart
max_exceeded: silent
variables:
palette: !input palette
idx_entity: !input index_helper
trigger:
- platform: event
event_type: zha_event
event_data:
device_id: !input switch_device
command: !input gesture
action:
- variables:
nxt: "{{ ((states(idx_entity) | int(0)) + 1) % ([ (palette | length), 1] | max) }}"
- action: input_number.set_value
target:
entity_id: !input index_helper
data:
value: "{{ nxt }}"
- variables:
entry: "{{ palette[nxt] }}"
# LED bar FIRST — it's a fast local write, so the bar updates immediately
# instead of waiting ~1s behind the slow Matter bulb call.
- choose:
- conditions: "{{ entry.led_hue is defined }}"
sequence:
- action: number.set_value
target:
entity_id: !input led_color_entity
data:
value: "{{ entry.led_hue | int }}"
# Bulb colour second (slow Matter call); continue_on_error so an unavailable
# group member can't abort anything after it.
- choose:
- conditions: "{{ entry.rgb_color is defined }}"
sequence:
- action: light.turn_on
continue_on_error: true
target:
entity_id: !input target_light
data:
rgb_color: "{{ entry.rgb_color }}"
default:
- action: light.turn_on
continue_on_error: true
target:
entity_id: !input target_light
data:
color_temp_kelvin: "{{ entry.color_temp_kelvin | int }}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment