Cycle through scenes with a button?

found good solution to reduce amount of code if you have many scenes.
Instead of commented block i used data_template. Works. Cheers

#   - alias: Yeelight Dim
#     trigger:
#       platform: state
#       entity_id: input_select.yeecolours
#       to: dim
#     action:
#       service: scene.turn_on
#       entity_id: scene.dim

#   - alias: Yeelight Bright
#     trigger:
#       platform: state
#       entity_id: input_select.yeecolours
#       to: bright
#     action:
#       service: scene.turn_on
#       entity_id: scene.bright

  - alias: Yeelight scenes
    trigger:
      platform: state
      entity_id: input_select.yeecolours
    action:
      service: scene.turn_on
      data_template:
        entity_id: scene.{{trigger.to_state.state}}
3 Likes

If you have spaces in your input_selects and scenes add these jinja2 filters | replace(" ","_") | lower

So like this:

- alias: Living Room Scenes
  trigger:
    platform: state
    entity_id: input_select.living_room_scenes
  action:
    - service: scene.turn_on
      data_template:
        entity_id: scene.{{trigger.to_state.state | replace(" ","_") | lower}}
3 Likes

I would love to use this solution for cycling through scenes (and playlist-entries) within Node-Red. Has anyone tried this perhaps? Will be thankful for any hints.

I’m using this:

in configuration.yaml

input_select:
   huiskamer_scenes:
     name: Huiskamer Scenes
     options:
       - uit (huiskamer)
       - soft achter (huiskamer)
       - soft voor en achter (huiskamer)
       - soft voor (huiskamer)
       - fel (huiskamer)
     initial: uit (huiskamer)
     icon: mdi:lightbulb-on-outline

and in automations.yaml

- id: '1583839323446'
  alias: zb switch A 2 huiskamer
  initial_state: 'on'
  trigger:
    platform: event
    event_type: deconz_event
    event_data:
      id:  zb_switch_a
  action:
  - service: input_select.select_option
    entity_id: input_select.huiskamer_scenes
    data_template:
      option: >
        {% set options = state_attr('input_select.huiskamer_scenes','options') -%}
        {% set selection = options.index(states('input_select.huiskamer_scenes')) -%}
        {% if trigger.event.data.event == 1002 -%}
          {% if (selection + 1) >= options | length -%}
            {{ options[1] }}
          {% else -%}
            {{ options[selection + 1] }}
          {% endif %}
        {% else %}
          {% if trigger.event.data.event == 2002 -%}
            {{ options[0] }}
          {% endif -%}
        {% endif -%}
  - service: scene.turn_on
    data_template:
      transition: 1
      entity_id: scene.{{states('input_select.huiskamer_scenes') | replace(" ","_") | replace("(","") | replace(")","") | lower}}

The options: script cycles through all options pressing the on (I) button, except for option 0 (off), which is only selected when the off (o) zigbee button is pressed.

I’m using the IKEA tradfri with deconz-II


https://phoscon.de/en/conbee2
3 Likes

To teach myself the new scripting features in 0.113, I modified your automation to use the new choose feature. It is useful when the action must choose between different services and especially when the services have different options. Although it can be done entirely with templates, the result is a bit messy; the choose feature makes it neater.

Here’s how it works:

  • If the event is 1002, it calls select_next.
  • If the event is 2002, it sets the input_select to its first option.
  • Finally, the action calls scene.turn_on and computes the scene’s name. I shortened the template slightly by using regex_replace to remove ( and ) characters.
- id: '1583839323446'
  alias: zb switch A 2 huiskamer
  initial_state: 'on'
  trigger:
    platform: event
    event_type: deconz_event
    event_data:
      id:  zb_switch_a
  action:
    - choose:
        - conditions:
            - condition: template
              value_template: "{{trigger.event.data.event == 1002}}"
          sequence:
            service: input_select.select_next
            entity_id: input_select.huiskamer_scenes
        - conditions:
            - condition: template
              value_template: "{{trigger.event.data.event == 2002}}"
          sequence:
            service: input_select.select_option
            data_template:
              entity_id: input_select.huiskamer_scenes
              option: "{{state_attr('input_select.huiskamer_scenes','options')[0]}}"
    - service: scene.turn_on
      data_template:
        transition: 1
        entity_id: >
          scene.{{states("input_select.huiskamer_scenes").replace(" ","_") | regex_replace(find="[\(\)]", replace="") | lower }}
4 Likes

Wow that looks lots better :grinning:
Only question I have is, in my earlier script it skipped option 0 as this is the Off option, which I do not want to cycle through.
How does your script prevent that ?

It doesn’t. All it was meant to do was serve as a demonstration of the use of choose to call two different services (select_next and select_option). If you need to skip option 0 then you’re better off using your original automation that calls just one service and uses a data_template.

1 Like

Clear, and yes I would use choose when possible, thanks for the heads up

I have used Taras code for cycling scenes in my house for some time now, and as far as I can see the best alternative I can find, but there are some issues:
My biggest problem is it looks like the automation has taken total control over my switches. I try to use the dim up and dim down buttons in two different automations to dim up and down the light. When I press one of those buttons, I see a short flicker in the light before it’s back to what was set in the scene. When I look in the core log I get these messages (AUR301_06: Dim down automation, AUR301_01: Cycle scene automation):

AUR301_06: Running automation actions
AUR301_06: Executing step device automation
AUR301_01: Running automation actions
AUR301_01: Executing step call service
AUR301_01: Running automation actions
AUR301_01: Executing step call service

So it looks like AUR301_01 is triggered even tho the dim up and dim down buttons are not mapped in that automation.

A similar thing happens when switching my house to night mode: I have an automation for long press off on all my dimmer switches that calls the night mode settings. When I long press the off button my whole house goes into night mode, except light in the room where I press the button. In this room light dims shortly before going back to the previous scene.

Another problem I have is after night mode has been triggered it looks like the first cycle scene press I do in a room recalls my last used scene or the next one in the list, not the first one.

It took some effort to find this post, but the reward is fine: just what I was looking for: scrolling through a series of scenes with one button. Clear explanation and great working example! Thanks!

1 Like

I solved this with two automations and one input_select.

The input_select's values are the scene IDs (without scene. because I don’t like repeating myself).

The first automation handles changing the input_select's value when I click the button:

alias: Living Room Scene Rotate
description: ''
trigger:
  - platform: device
    domain: mqtt
    device_id: b7dd...
    type: click
    subtype: 'on'
    discovery_id: 0x000d... click_on
condition: []
action:
  - service: input_select.select_next
    target:
      entity_id: input_select.living_room_scenes
mode: single

The other automation is activated when that input_select changes and activates the selected scene with a template that reads the input_select's value.

alias: Living Room Scene Activate
description: ''
trigger:
  - platform: state
    entity_id: input_select.living_room_scenes
condition: []
action:
  - service: scene.turn_on
    target:
      entity_id: scene.{{ states('input_select.living_room_scenes') }}
mode: single
6 Likes

Im struggling hard. With my HUE Button, this works but with the Ikea Button I cannot get those scene working:

    action_button_down_short:
      - service: input_select.select_next
        data:
          cycle: true
        target:
          entity_id: input_select.scene_buro
      - service: scene.turn_on
        target:
          entity_id: "{{states('input_select.scene_buro')}}"

So the Problem is. It switches the scenes, but it’s unable to apply the scene then.
What am I doing wrong? Same script, works on the Hue Dimmer Switch…

Thanks!!! Cycling works great.

Hi,

I use this script to cycle through scenes it’s working but not always.
It changes the input select perfect but is only randomly actually changes the scene. On the dashboard I see the scene changing it’s just not applied to the lights sometimes. This usually happens when cycle a bit faster.
I have tried different modes (single, restart, queued) but that didn’t change anything.

Any help (also how to debug) would be much appreciated. I am pretty new to HASS

- service: input_select.select_next
  data:
    cycle: true
  target:
    entity_id: input_select.keuken_scenes
- service: scene.turn_on
  target:
    entity_id: >-
      {{'scene.' + states('input_select.keuken_scenes').replace("
      ","_").lower()}}

BTW I use Zigbee2MQTT

An update on my own post.

I’ve tried to solve it via MQTT this works a lot better but still not 100%.

alias: Test Scene selector (MQTT)
sequence:
  - service: input_select.select_next
    data:
      cycle: true
    enabled: true
    target:
      entity_id: input_select.keuken_scene_mqtt
  - service: mqtt.publish
    data:
      topic: zigbee2mqtt/Keuken Lampen/set
      payload_template: "{\"scene_recall\": {{ states('input_select.keuken_scene_mqtt') }} }"
      qos: "0"
mode: queued
max: 12

BTW to make it work fill the input_select.keuken_scene_mqtt with the number of the scenes (scene id from Zigbee2MQTT) something like 0, 1, 2, 3

Now how to take account light color at the start?

Ie. I have light toggle and then warm cold pink, it starts on pink, first scene in cycle happens to be pink so it does not change.

Any super nice way to do this?


I do get why this does not work as expected with turn off button action, but it does change the scene (color temp.) only after I press on the light switch again, triggering light toggle.
When switching scenes from HA UI it does switch color temp.

I do get “triggered” when watching scene dialog when I hold the button for about 4 sec. so that seems all ok.


6 years old thread now :smiley:

Using the following Blueprint made it easy for me.
:next_track_button: Simple Scene Toggle - Blueprints Exchange - Home Assistant Community (home-assistant.io)

How I’ve done it today:

  1. Made some Scenes in the GUI.
  2. Made a Dropdown Helper in the GUI – the Options were the scenes names (names! not IDs!)
  3. Made an Automation that activates the matching Scene when Dropdown option is selected (notice slugifying of the scene names!):
      alias: TV scenes activation
      description: ""
      trigger:
        - platform: state
          entity_id:
            - input_select.tv_scenes
      condition: []
      action:
        - service: scene.turn_on
          metadata: {}
          target:
            entity_id: "{{ 'scene.' + slugify(states.input_select.tv_scenes.state) }}"
      mode: single
    
  4. Finally made an Automation that cycles the Dropdown’s options upon a (zigbee) button click:
        alias: Button switching TV scenes
        description: ""
        trigger:
          - device_id: <redacted>
            domain: zha
            platform: device
            type: remote_button_short_press
            subtype: button_1
        condition: []
        action:
          - service: input_select.select_next
            target:
              entity_id:
                - input_select.tv_scenes
            data:
              cycle: true
        mode: single
    
1 Like

i followed a different approach, storing the number how often on was pressed in a persistent variable. The blueprint is for homematic button devices, but will work with some adoption for other devices as well.

blueprint:
  name: HM Push Button Light on/off/dim or next scene 
  description: >-
    A script to connect a push button device with a light. The script can switch the light on and off on short keypress
    and dim up and down on long keypress. If the light is on and the on button is pressed another time, the automation 
    switch throuh different scenes.
    It require the variable saver addon from here: https://github.com/PiotrMachowski/Home-Assistant-custom-components-Saver
  domain: automation

  input:
    pushbtn_dev:
      name: HM Push Button Device
      description: Please select a Button device of your Homematic integration.
      selector:
        device:
          integration: homematicip_local
    on_button:
      name: On Button
      description: "Align button channel to on function"
      selector:
        number:
          min: 0
          max: 12
    off_button:
      name: Off Button
      description: "Align button channel to off function"
      selector:
        number:
          min: 0
          max: 12
    light_dev:
      name: Light
      description: "Light device for on/off and dim"
      default: []
      selector:
        entity:
          multiple: true
          domain: light
    off_scene:
      name: Off Button Scene     
      description: "Select a script or scene which shall be executed when the off button is two times pressed"
      default: []
      selector:
        entity:
          multiple: true
          filter:
            domain: 
              - scene
              - script              
    scene_1:
      name: Scene 1    
      description: "Select a scene"
      default: []
      selector:
        entity:
          multiple: true
          filter:
            domain: 
              - scene
              - script              
    scene_2:
      name: Scene 2    
      description: "Select a scene"
      default: []
      selector:
        entity:
          multiple: true
          filter:
            domain: 
              - scene
              - script              
    scene_3:
      name: Scene 3    
      description: "Select a scene"
      default: []
      selector:
        entity:
          multiple: true
          filter:
            domain: 
              - scene
              - script              
    scene_4:
      name: Scene 4    
      description: "Select a scene"
      default: []
      selector:
        entity:
          multiple: true
          filter:
            domain: 
              - scene
              - script              


trigger:
- platform: event
  event_type: homematic.keypress
  event_data:
    device_id: !input pushbtn_dev


variables:
  light_dev:   !input 'light_dev'
  pushbtn_dev: !input 'pushbtn_dev'
  on_button:   !input 'on_button'
  off_button:  !input 'off_button'
  
  #                 0                  1                  2                  3                 4                 5                 6  
  target: [!input 'off_scene',!input 'light_dev',!input 'light_dev',!input 'scene_1', !input 'scene_2', !input 'scene_3', !input 'scene_4']

  # adjust and combine trigger, to have one point to adopt other switches
  event_key: >
    {% if trigger.event.data.type  == 'press_short' and trigger.event.data.subtype  == on_button %} 
      short_on 
    {% elif trigger.event.data.type  == 'press_short' and trigger.event.data.subtype  == off_button %} 
      short_off 
    {% elif trigger.event.data.type  == 'press_long' or trigger.event.data.type  == 'press_cont' and trigger.event.data.subtype  == on_button %} 
      long_on 
    {% elif trigger.event.data.type  == 'press_long' or trigger.event.data.type  == 'press_cont' and trigger.event.data.subtype  == off_button %} 
      long_off
    {% endif %} 

  # get counter from memory, decide based on trigger and subtrigger what to do
  # 0: short_off, coming from 1 and if target[0] is defined
  # 1: short_off but only if we switched not to 0
  #
  # 2: short_on while coming from 0 or 1, or coming from 2 and target[3] is not defined
  # 3: short_on while coming from 2 and target[3] is defined
  # 4: short_on while coming from 3 and target[4] is defined
  # 5: short_on while coming from 4 and target[5] is defined
  # 6: short_on while coming from 5 and target[6] is defined
  #  : next short_on returns to 3
  keycnt: >
    {% set t_cnt = saver_variable(trigger.event.data.device_id) or 0 %}
    {% if event_key == 'short_on' %} 
      {% if   t_cnt == '0' or t_cnt == '1' %}   {% set x_cnt = 2 %} 
      {% elif t_cnt == '2' and not target[3] %} {% set x_cnt = 2 %} 
      {% elif t_cnt == '2' and target[3] %}     {% set x_cnt = 3 %} 
      {% elif t_cnt == '3' and target[4] %}     {% set x_cnt = 4 %} 
      {% elif t_cnt == '4' and target[5] %}     {% set x_cnt = 5 %} 
      {% elif t_cnt == '5' and target[6] %}     {% set x_cnt = 6 %} 
      {% else %}                                {% set x_cnt = 3 %} 
      {% endif %} 

    {% elif event_key == 'short_off' %} 
      {% if t_cnt == '1' and target[0] %}       {% set x_cnt = 0 %}
      {% else %}                                {% set x_cnt = 1 %} 
      {% endif %} 
 
    {% elif event_key == 'long_on' or event_key == 'long_off' %} 
      {% set x_cnt = 2 %} 

    {% endif %} 
    {{x_cnt}}


  # find the correct service, depending on the service domain
  target_service: >
    {% if not target[keycnt] %}
      none    
    {% elif states[target[keycnt][0]].domain == 'scene' %} 
      scene.turn_on 
    {% elif states[target[keycnt][0]].domain == 'script' %} 
      script.turn_on
    {% elif states[target[keycnt][0]].domain == 'light' and keycnt == 1  %} 
      light.turn_off
    {% elif states[target[keycnt][0]].domain == 'light' and keycnt == 2 %} 
      light.turn_on
    {% endif %} 
  
  
  # assign entity_id based on state_cntr
  target_details:  >
    {% if states[target[keycnt][0]].domain == 'script' %} 
      {{ {"entity_id": target[keycnt] } }}
    {% else %}   
      {{ {"entity_id": target[keycnt], "transition": 0.5 } }}
    {% endif %} 
  

  
condition: []

action:
- choose:
  # a short press is switching the light on or a scene select if it was a repeated on press
  - conditions: '{{ event_key  == ''short_on'' or event_key  == ''short_off'' and target_service != ''none'' }}'
    sequence:  
    - service: '{{ target_service }}'
      data: '{{ target_details }}'

  # press the first button continous means dim the light up
  - conditions: '{{ event_key  == ''long_on'' and target_service != ''none'' }}'
    sequence: 
    - service: '{{ target_service }}'
      data:
        entity_id: '{{ target[keycnt] }}'
        transition: 0.2
        brightness_step: 20    

  # press the second button continous means dim the light down
  - conditions: '{{ event_key  == ''long_off'' and target_service != ''none'' }}'
    sequence: 
    - service: '{{ target_service }}'
      data:
        entity_id: '{{ target[keycnt] }}'
        transition: 0.2
        brightness_step: >
          {% set brightness = state_attr(light_dev[0], 'brightness') or 0 %}  
          {% if brightness < 3 %} {% set step = 0 %}
          {% elif brightness < 22 %} {% set step = -(brightness - 2) %}
          {% else %} {% set step = -20 %}
          {% endif %}        
          {{ step }}

# save the value in a secure store for next time usage
- service: saver.set_variable
  data:
    name: '{{ trigger.event.data.device_id }}'
    value: '{{ keycnt }}'

mode: queued
max: 5

thank you so much, this was so easy and did exactly what i wanted :slight_smile: