Some hardware links on this page are affiliate links. As an Amazon Associate I earn from qualifying purchases. We may earn a commission if you buy through them, at no extra cost to you. See the affiliate disclosure.
A pile of scene buttons on one remote is how you get the wrong purple. This workflow uses one button: each short press advances a counter and turns on the next scene in a list you order. Sit idle past a timeout and the counter goes back to zero so the next evening starts on the first scene again. A long press — or one more short press after the last scene — runs homeassistant.turn_off on the targets and resets the counter.
Entity ids are blueprint inputs. Do not publish a live room’s scene names.
What problem it solves
You want a single hallway or nightstand button that walks “dim → reading → bright” and then off, without a second “off” paddle if the hardware does not have one, and without leaving the counter stuck on scene three tomorrow.
How it works
- Short press — increment
counter.scene_step(step size 1). If the new value is still inside the scene list,scene.turn_onthat index (1-based). The first press after a reset always hits the first scene. - Past the last scene — if the counter would exceed the list length, skip the scene call, turn the target lights/switches off, and
counter.reset. That last extra tap is the off command on a single-button remote. - Long press — same off + reset path, immediately. Use this when the device exposes
long/hold(ESPHomeon_multi_click, Zigbeehold, Hue-class event entities). If the button is short-only, the wrap-around off is enough. - Idle timeout — after the last press, wait the idle window (pack default a few minutes). If nobody presses again, reset the counter without changing lights. The room stays as it is; the next short press starts at scene one instead of “whatever we left.”
- Restart-safe step — the counter helper is the memory. An automation variable dies on reboot; the counter does not, so a press after a HA restart continues from the stored step (until idle timeout fires).
Put the scene you want first in the list. Off is not a scene; it is the wrap / long-press path.
Hardware notes
- ESPHome GPIO. A momentary pushbutton to ground with
pullupandon_multi_click(short vs long). Any small ESP32 or an existing node with a spare pin. - Zigbee / Z-Wave remote. A device that publishes short and (ideally) long events. One button is enough; a separate off button can call the same off script if you have one.
- Wall switch. A smart switch in detached / event mode, or a scene paddle. Do not use a switch that cuts mains to the lamps you are dimming if the bulbs need constant power.
- Scenes. HA
sceneentities. Keep them in one area so “off” has a clear target list (the same lights the scenes own).
Snippet
The pack ships a blueprint. Inputs replace real entity ids:
trigger:
- platform: state
entity_id: !input button_short
to: "on"
id: short
- platform: state
entity_id: !input button_long
to: "on"
id: long
- platform: state
entity_id: !input scene_counter
id: stepped
# idle reset uses a wait / timer in the full blueprint
action:
- choose:
- conditions:
- condition: trigger
id: short
sequence:
- service: counter.increment
target:
entity_id: !input scene_counter
- variables:
step: "{{ states(scene_counter) | int(0) }}"
scenes: !input scene_list
- choose:
- conditions:
- condition: template
value_template: "{{ step <= scenes | count }}"
sequence:
- service: scene.turn_on
target:
entity_id: "{{ scenes[step - 1] }}"
default:
- service: homeassistant.turn_off
target:
entity_id: !input off_targets
- service: counter.reset
target:
entity_id: !input scene_counter
- conditions:
- condition: trigger
id: long
sequence:
- service: homeassistant.turn_off
target:
entity_id: !input off_targets
- service: counter.reset
target:
entity_id: !input scene_counter
Optional ESPHome button (credentials stay in secrets.yaml):
binary_sensor:
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: true
name: "Scene button"
on_multi_click:
- timing:
- ON for at most 400ms
then:
- homeassistant.event:
event: esphome.scene_button
data:
click: short
- timing:
- ON for at least 800ms
then:
- homeassistant.event:
event: esphome.scene_button
data:
click: long
Setup outline
- Create the scenes in the order you want to walk. Create
counter.scene_step(minimum 0, step 1). - Confirm the button’s short (and long, if any) entities in Developer Tools.
- Import the blueprint. Fill button entities, scene list, off targets, counter, idle timeout.
- Test: short, short, short → scenes 1, 2, 3; one more short → off and counter 0; long press from any step → off; wait the idle timeout after scene 2 → next short is scene 1.
Troubleshooting
- Skips a scene. The counter step is not 1, or you incremented twice (two automations on the same button). One blueprint instance per button.
- Never reaches off. The wrap check uses a different list length than the scenes you selected, or long-press is wired to the short entity. Count the list; fire long from Developer Tools.
- Next day starts on the last scene. Idle timeout never ran (automation disabled, or timeout longer than you think). Lower it, or reset the counter from the off path only and accept that a reboot mid-evening keeps the step — that is the restart-safe part.
- GPIO short and long both fire.
on_multi_clicktimings overlap. Shorten the short window and lengthen the longON for at leastso they cannot both match.
Credits
Based on the community blueprint Button Scene Cycling and Off Control. This write-up is an original overview of a one-button counter cycle with idle reset and wrap-to-off.