Cycle through light effects via button press

Hi everyone,
I have the following light in ESPHome:

light:
  - platform: neopixelbus
    variant: WS2812x
    type: GRB
    color_correct: [80%, 80%, 80%] 
    pin: GPIO26
    num_leds: 3
    name: "Front Light"
    id: front_light
    effects:
      - addressable_rainbow
      - addressable_color_wipe
      - addressable_scan
      - addressable_twinkle
      - addressable_random_twinkle
      - addressable_fireworks
      - addressable_flicker
    on_turn_on:
      then:
        - if:
            condition:
              - lambda: 'return id(front_light).remote_values.get_brightness() < 0.2;'
            then:
              - light.turn_on: 
                  id: front_light
                  brightness: 0.25

I also have this button:

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO19
      mode:
        input: true
        pullup: true
      inverted: True
    name: "Rotary Encoder Button"
    id: front_rotary_button
    internal: false
    on_multi_click:
      #Double Click
      - timing:
          - ON for at most 0.5s
          - OFF for at most 0.3s
          - ON for at most 0.5s
          - OFF for at least 0.2s
        then:
          - if:
              condition:
                light.is_on: front_light
              then:
                - light.control:
                    id: front_light
                    effect: "Rainbow"
      #Hold
      - timing:
          - ON for at least 0.75s
        then:
          light.toggle:
            id: front_light
            transition_length: 1s

I am trying to achieve that a double click on the button cycles through all of the available effects the light offers. Is there anyway to do this? So one double clicks picks the first, a second one the next until we are at no effect again.

Best,
Paul

1 Like

Found a solution for my problem.
Using the global variable:

globals:
   - id: active_effect
     type: int
     restore_value: yes
     initial_value: '0' 

And then the lambda in the click action:

- lambda: !lambda |-
                    id(active_effect) += 1;
                    auto call = id(front_light).turn_on();
                    switch (id(active_effect)) {
                      case 1:
                        call.set_effect("Rainbow");
                        break;
                      case 2:
                        call.set_effect("Color Wipe");
                        break;
                      default:
                        id(active_effect) = 0;
                        call.set_effect("None");
                        break;
                    }
                    call.perform();
3 Likes

This helped me out - thanks!

1 Like

Nice to hear!