esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 36 forks source link

Multi-Click - At Least timing #2825

Closed torianironfist closed 2 years ago

torianironfist commented 2 years ago

The problem

I have a standard toggle (not momentary) switch at the top of my basement stairs with a Shelly 1PM installed. I would like to use this switch to switch the relay normally when switched once and turn off all the basement lights when switched twice quickly. I wrote some yaml for a binary sensor using on_multi_click.

It works with a couple problems, the first switch after booting does not trigger an action and the next switch after the "double click" action also does not trigger.

As far as I can tell, the issue is starting a multi-click timing with the "at least" grammar. When first booted or flashed, the timing is not initialized, so it cannot time "at least" until the switch has been toggled once and it appears a similar thing happens after the "double click", it no longer keeps track of the timing between the last switch.

Which version of ESPHome has the issue?

2021.12.0

What type of installation are you using?

Docker

Which version of Home Assistant has the issue?

2021.12.1

What platform are you using?

ESP8266

Board

Shelly 1PM

Component causing the issue

Binary Sensor

Example YAML snippet

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO4
    id: switchid
    on_multi_click:
      - timing:
          - ON for at most 0.3s
          - OFF for at least 0.2s
        then:
          - homeassistant.service:
              service: light.turn_off
              data:
                entity_id: light.group
          - logger.log: "Double-Click - Off to On to Off"
      - timing:
          - OFF for at most 0.3s
          - ON for at least 0.2s
        then:
          - homeassistant.service:
              service: light.turn_off
              data:
                entity_id: light.group
          - logger.log: "Double-Click - On to Off to On"
      - timing:
          - ON for at least 0.5s
          - OFF for at least 0.5s
        then:
          - switch.toggle: shelly_relay
          - logger.log: "Single-Click - On to Off"
      - timing:
          - OFF for at least 0.5s
          - ON for at least 0.5s
        then:
          - switch.toggle: shelly_relay
          - logger.log: "Single-Click - Off to On"

Anything in the logs that might be useful for us?

[14:03:47][I][ota:102]: Boot seems successful, resetting boot loop counter.
[14:05:26][D][binary_sensor:036]: 'switchid': Sending state ON
[14:05:26][V][binary_sensor.automation:025]: START min=0 max=300
[14:05:26][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:05:26][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:05:26][V][binary_sensor.automation:025]: START min=500 max=4294967294
[14:05:26][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:05:26][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:05:26][V][binary_sensor.automation:095]: Multi Click: You waited too long to RELEASE.
[14:05:26][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:05:26][V][binary_sensor.automation:089]: Multi Click: You can now RELEASE the button.
[14:05:27][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[14:05:29][D][binary_sensor:036]: 'switchid': Sending state OFF
[14:05:29][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:05:29][V][binary_sensor.automation:025]: START min=0 max=300
[14:05:29][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:05:29][V][binary_sensor.automation:062]: C i=1 min=500
[14:05:29][V][binary_sensor.automation:025]: START min=500 max=4294967294
[14:05:29][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:05:29][V][binary_sensor.automation:095]: Multi Click: You waited too long to PRESS.
[14:05:29][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:05:29][V][binary_sensor.automation:101]: Multi Click: Hooray, multi click is valid. Triggering!
[14:05:29][D][switch:021]: 'Light' Toggling OFF.
[14:05:29][D][switch:037]: 'Light': Sending state OFF
[14:05:29][D][main:396]: Single-Click - On to Off
[14:05:29][V][binary_sensor.automation:089]: Multi Click: You can now PRESS the button.
[14:05:30][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[14:05:32][D][binary_sensor:036]: 'switchid': Sending state ON
[14:05:32][V][binary_sensor.automation:025]: START min=0 max=300
[14:05:32][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:05:32][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:05:32][V][binary_sensor.automation:025]: START min=500 max=4294967294
[14:05:32][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:05:32][V][binary_sensor.automation:062]: C i=1 min=500
[14:05:32][V][binary_sensor.automation:095]: Multi Click: You waited too long to RELEASE.
[14:05:32][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:05:32][V][binary_sensor.automation:089]: Multi Click: You can now RELEASE the button.
[14:05:32][V][binary_sensor.automation:101]: Multi Click: Hooray, multi click is valid. Triggering!
[14:05:32][D][switch:021]: 'Light' Toggling ON.
[14:05:32][D][switch:037]: 'Light': Sending state ON
[14:05:32][D][main:414]: Single-Click - Off to On
[14:05:33][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[14:06:02][D][binary_sensor:036]: 'switchid': Sending state OFF
[14:06:02][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:06:02][V][binary_sensor.automation:025]: START min=0 max=300
[14:06:02][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:06:02][V][binary_sensor.automation:062]: C i=1 min=500
[14:06:02][V][binary_sensor.automation:025]: START min=500 max=4294967294
[14:06:02][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:06:03][D][binary_sensor:036]: 'switchid': Sending state ON
[14:06:03][V][binary_sensor.automation:025]: START min=0 max=300
[14:06:03][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:06:03][V][binary_sensor.automation:062]: C i=1 min=200
[14:06:03][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:06:03][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:06:03][V][binary_sensor.automation:101]: Multi Click: Hooray, multi click is valid. Triggering!
[14:06:03][D][main:346]: Double-Click - On to Off to On
[14:06:03][V][binary_sensor.automation:095]: Multi Click: You waited too long to RELEASE.
[14:06:03][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:06:04][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[14:06:04][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[14:06:04][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[14:06:08][D][binary_sensor:036]: 'switchid': Sending state OFF
[14:06:08][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:06:08][V][binary_sensor.automation:025]: START min=0 max=300
[14:06:08][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:06:08][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:06:08][V][binary_sensor.automation:025]: START min=500 max=4294967294
[14:06:08][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:06:08][V][binary_sensor.automation:095]: Multi Click: You waited too long to PRESS.
[14:06:08][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:06:09][V][binary_sensor.automation:089]: Multi Click: You can now PRESS the button.
[14:06:09][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[14:06:13][D][binary_sensor:036]: 'switchid': Sending state ON
[14:06:13][V][binary_sensor.automation:025]: START min=0 max=300
[14:06:13][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:06:13][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[14:06:13][V][binary_sensor.automation:025]: START min=500 max=4294967294
[14:06:13][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[14:06:13][V][binary_sensor.automation:062]: C i=1 min=500
[14:06:13][V][binary_sensor.automation:095]: Multi Click: You waited too long to RELEASE.
[14:06:13][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[14:06:14][V][binary_sensor.automation:089]: Multi Click: You can now RELEASE the button.
[14:06:14][V][binary_sensor.automation:101]: Multi Click: Hooray, multi click is valid. Triggering!
[14:06:14][D][switch:021]: 'Light' Toggling OFF.
[14:06:14][D][switch:037]: 'Light': Sending state OFF
[14:06:14][D][main:414]: Single-Click - Off to On
[14:06:14][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.

Additional information

No response

probot-esphome[bot] commented 2 years ago

Hey there @esphome/core, mind taking a look at this issue as it has been labeled with an integration (binary_sensor) you are listed as a code owner for? Thanks! (message by CodeOwnersMention)

torianironfist commented 2 years ago

If anyone else runs into this, I was able to create a workaround with lambdas. This is only set up to distinguish between single and double clicks, but could be extrapolated further if more complex patterns were needed.

esphome:
  on_boot:
    then:
      - lambda: |-
          id(multi_click_time) = millis();

globals:
  - id: multi_click_time
    type: int
    restore_value: no
  - id: single_click
    type: bool
    restore_value: no

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO5
    id: switch
    on_state:
      then:
        - if: 
            condition:
              lambda: 'return millis() - id(multi_click_time) > 500;'
            then:
              - lambda: 'id(multi_click_time) = millis(); id(single_click) = true;'
            else: 
              - lambda: 'id(multi_click_time) = millis();'
              - logger.log: "Double Click Detected!"
              # Double click action here
        - delay: .5s
        - if: 
            condition:
              lambda: 'return id(single_click) == true && millis() - id(multi_click_time) > 500;'
            then:
              - lambda: 'id(single_click) = false;'
              - logger.log: "Single Click Detected!"
              # Single click action here
            else: 
              - lambda: 'id(single_click) = false;'
jesserockz commented 2 years ago

Something I have done to get around this was to make a template binary sensor, and turn that binary sensor on, delay 50ms and turn back off again, so basically turning every state change (off to on or on to off) into a click and doing the timing logic in that template binary sensor.

jesserockz commented 2 years ago
binary_sensor:
- platform: gpio
  id: raw_switch
  pin:
    number: 0
    mode: INPUT_PULLUP
  on_state:
    then:
      - binary_sensor.template.publish:
          id: switch_clicker
          state: ON
      - delay: 100ms
      - binary_sensor.template.publish:
          id: switch_clicker
          state: OFF

- platform: template
  id: switch_clicker
  name: ${friendly_name}
  on_multi_click:
  - timing:
    - ON for at most 0.2s
    - OFF for at least 0.5s
    then:
      # single "click" actions - up or down once only
  - timing:
    - ON for at most 0.2s
    - OFF for at most 0.5s
    - ON for at most 0.2s
    - OFF for at least 0.5s
    then:
      # double click actions - up down, or down up
torianironfist commented 2 years ago

Making the template into a faux momentary switch. Brilliant. That is much easier to read than my code. Thanks very much.

10bn commented 2 years ago

this is great, thx!

torianironfist commented 2 years ago

This is such an easy work around and this issue doesn't seem to be affecting many people, so I am just going to close this.

10bn commented 2 years ago

For those looking for a complete example, this will give you three entities which binary state will be toggled on a single, double or tripple click.

binary_sensor:

# Wall Swtich 1
  - platform: gpio
    pin:
      number: GPIO14
      mode: INPUT
    id: sensorid1
    filters:
      - delayed_on_off: 80ms # Debounce filter to eliminate random false switching. 
    on_state:
      then:
        - binary_sensor.template.publish:
            id: switch_clicker
            state: ON
        - delay: 100ms
        - binary_sensor.template.publish:
            id: switch_clicker
            state: OFF

  - platform: template
    id: switch_clicker
    on_multi_click:
      - timing:
        - ON for at most 0.5s
        - OFF for at least 0.5s
        then:
          - logger.log: "Single Click"
          - lambda: |-
              if (id(template_sensor_1).state) {
              id(template_sensor_1).publish_state(false);
              } else { 
              id(template_sensor_1).publish_state(true);
              }

      - timing:
          - ON for at most 0.5s
          - OFF for at most 0.5s
          - ON for at most 0.5s
          - OFF for at least 0.5s
        then:
          - logger.log: "Double Click"
          - lambda: |-
              if (id(template_sensor_2).state) {
              id(template_sensor_2).publish_state(false);
              } else {
              id(template_sensor_2).publish_state(true); 
              }

      - timing:
          - ON for at most 0.5s
          - OFF for at most 0.5s
          - ON for at most 0.5s
          - OFF for at most 0.5s
          - ON for at most 0.5s
          - OFF for at least 0.2s
        then:
          - logger.log: "Tripple Click"
          - lambda: |-
              if (id(template_sensor_3).state) {
              id(template_sensor_3).publish_state(false);
              } else {
              id(template_sensor_3).publish_state(true); 
              }

  - platform: template
    name: Remote 1 $friendly_name
    id: template_sensor_1
  - platform: template
    name: Remote 2 $friendly_name
    id: template_sensor_2
  - platform: template
    name: Remote 3 $friendly_name
    id: template_sensor_3
SmoothSilence commented 2 years ago

Hi guys. I came across the same problem but I use the mult-click for a LED strip. The idea was a single press turns it on or off, double click goes to max-min brightness of the LED strip and hold slowly dims up or down the strip till you let go. Besides physical push buttons I use HA too. On both sides HA and wall buttons I have that error and it turns off the LED strip Could you point me to where I messed up here ?

esphome:
  name: yard

esp32:
  board: esp32dev

# Enable Home Assistant API
api:
  #password: !secret api_password

ota:
  password: "d38824f1345be0b6847b1085aa7929da"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Yard Fallback Hotspot"
    password: "075664688s"
captive_portal:

status_led:
  pin:
    number: 2
    inverted: True

# Enable logging
debug:

logger:
  level: VERBOSE #Change the log level as required; during testing verbose is helpful. 
  baud_rate: 0

globals:
  # Za Tenda led strip globals
  - id: light_tenda_min_brightness  #min brighness for Tenda led
    type: float
    restore_value: no
    initial_value: '0.05'
  - id: light_tenda_max_brightness   #max brightness za Tenda LED
    type: float
    restore_value: no
    initial_value: '1.0'
  - id: dim_direction_tenda   #nasoka (pojachuva ili stishuva led lentata) dirrection going up or down
    type: int
    restore_value: no
    initial_value: '1'
  - id: TENDA_loop_stop # kraj chitanje taster na najmal ili najgolem brightness (stops loop if at max or min)
    type: bool
    restore_value: no
    initial_value: 'false'
  - id: step #dimmer steps
    type: float
    restore_value: no
    initial_value: '0.02'

# sensor to report wifi RSSI

binary_sensor:
  # Tenda taster: button for LED strip
  - platform: gpio
    pin:
      number: GPIO36
      mode: INPUT
      inverted: True
    name: "Tenda Taster"
    id: light_tenda_button
    # we  use multi_click to get both single and double click
    # single click to turn on and off (toggle)
    # double click to set either max or min brightness: if currently off then turn on with brightness=max. If currently on, then if currently brigthness equals max then set to min, else set to max
    on_multi_click:
    - timing:
      - ON for at most 1s
      - OFF for at most 1s
      - ON for at most 1s
      - OFF for at least 0.2s
      then:
        - logger.log: "on_multi_click: dupli klik max min"
        - if:
           condition: 
             light.is_off: tenda_led
           then:
             - light.turn_on: 
                id: tenda_led
                brightness: !lambda |-
                  return id(light_tenda_max_brightness);
             - delay: 1s
        - if:
           condition: 
             light.is_on: tenda_led
           then:
             - light.turn_on: 
                id: tenda_led
                # if currently off then turn on with brightness=max. If currently on, then if currently brigthness equals max then set to min, else set to max:
                brightness: !lambda |-
                  float brightness;
                  id(tenda_led).current_values_as_brightness(&brightness);
                  if (brightness >= id(light_tenda_max_brightness)) {
                    return id(light_tenda_min_brightness);
                  }
                  else {
                    return id(light_tenda_max_brightness);
                  } 
             - delay: 1s

    # single click to turn on and off (toggle):
    - timing:
      - ON for at most 1s
      - OFF for at least 0.5s
      then:
        - logger.log: "on_multi_click: pali ili gasi eden stisok"
        - light.toggle: tenda_led
        - delay: 1s

    # Long press to dim up and down:  
#    on_multi_click:
    - timing:
      - ON for at least 2s
      - OFF for at least 0.5s
      then:
        - logger.log: "pijachuva ili stishuva"
      # we need this delay (and then to look for binary_sensor.is_on) to ensure it's not a multi-click
        - delay: 0.8s 
        - if:
            condition: 
               and:
               - light.is_off: tenda_led
               - binary_sensor.is_on: light_tenda_button
            then:
             # if the light was off we also want the long press to turn it on and then start dimming
             - light.toggle: tenda_led
         #    - delay: 0.75s
      #
      # this sets the globales variable that will stop the while loop from needlessly running if the buttons keeps being pressed but ar are already at max or min value
        - lambda: |-
             id(TENDA_loop_stop) = false;
        - while:
          # keep on going as long as the button is pressed and when the max/min threshold is not exceeded yet (indicated by the global var of type bool)
            condition:
              and:
                 - binary_sensor.is_on: light_tenda_button
                 - lambda: |-
                     return(!id(TENDA_loop_stop));
            then:
              - light.dim_relative: 
                    id: tenda_led
                  # This lambda will dim up or down depending on the dim direction
                  # if dim = up, it will keep increasing brightness with global var 'step' (so we can easily change this in a central place) as long as the button keeps being pressed until max_brightness would be exceed
                  # in the case it will set it to max brightness, beep the buzzer once (the buzzer is defined as a light with effect "beeponce") and then stop the loop - this both prevent further needless loops as well as ensures the buzzer only buzzes once
                  # if dim = down, it will keep decreasing brightness with global var 'step' (so we can easily change this in a central place) as long as the button keeps being pressed until min_brightness would be exceed
                  # in the case it will set it to min brightness, beep the buzzer once (the buzzer is defined as a light with effect "beeponce") and then stop the loop - this both prevent further needless loops as well as ensures the buzzer only buzzes once
                    relative_brightness: !lambda |-
                          float brightness;
                          float gamma;
                          id(tenda_led).current_values_as_brightness(&brightness);
                          // this is the gamma corrected value - we need to 'un'compensate for gamma to get a lineair %value
                          gamma = id(tenda_led).get_gamma_correct();
                          brightness = powf(brightness,1/gamma);
                          //id(tenda_led).dump_config();
                          ESP_LOGD("main", "while loop, dim=%d, brightness=%6.4lf, step=%6.4lf, max=%6.4lf, gamma=%6.4lf", id(dim_direction_tenda), brightness,id(step),id(light_tenda_max_brightness),gamma);
                          if (brightness >= id(light_tenda_max_brightness)) {
                           // if we are at max already, no point in dimming up - this will ever happen at loop start because of the loopstop break, so no issues with the loop
                           id(dim_direction_tenda) = '0';
                          }
                          else if (brightness <= id(light_tenda_min_brightness)) {
                           // if we are at min already, no point in dimming down - this will ever happen at loop start because of the loopstop break, so no issues with the loop
                             id(dim_direction_tenda) = '1';
                          }
                          if (id(dim_direction_tenda) == '1') {
                             if ((id(step) + brightness) <= id(light_tenda_max_brightness)) { 
                                return(id(step));
                           }
                             else {
                              //  auto call = id(light_buzzer).turn_on();
                              //  call.set_effect("beeponce");
                              //  call.perform();
                                id(TENDA_loop_stop) = true;
                                return(id(light_tenda_max_brightness)- brightness);
                             }
                          }
                          else if (id(dim_direction_tenda) != '1') {
                             if ((brightness - id(step)) >= id(light_tenda_min_brightness)) { 
                              return(-id(step));
                             }
                             else {
                               // auto call = id(light_buzzer).turn_on();
                               // call.set_effect("beeponce");
                               // call.perform();
                                id(TENDA_loop_stop) = true;                          
                               return(id(light_tenda_min_brightness)- brightness);
                             } 

                          }
                          // the else is strictly speaking not needed as the loop should break before this condition is true but if for whatever reason that would not happen at least we are returning something
                          else {
                            return(0);
                          }
                    transition_length: 0.05s
              - delay: 0.5s
      # now toggle the dim up/down direction so next time we do the opposite action
        - globals.set:
            id: dim_direction_tenda
            value: !lambda |-
              if (id(dim_direction_tenda) == '1') {
                  return('0');
              } else {
                return('1');
              }

  - platform: gpio
    pin:
      number: GPIO39
      mode: INPUT
      inverted: True
    filters:
    - delayed_on: 50ms
    name: "Radio Taster"
    id: button_radio
    on_press:
      then:
        - if:
           condition: 
             light.is_off: light_radio
           then:
             - light.turn_on: light_radio
             - delay: 1s
           else:
             - light.turn_off: light_radio
             - delay: 1s

  - platform: gpio
    pin:
      number: GPIO34
      mode: INPUT
      inverted: True
    filters:
    - delayed_on: 50ms
    name: "Fasada Kupatilo Taster"
    id: button_fasada_kupatilo
    on_press:
      then:
        - if:
           condition: 
             light.is_off: light_fasada_kupatilo
           then:
             - light.turn_on: light_fasada_kupatilo
             - delay: 1s
           else:
             - light.turn_off: light_fasada_kupatilo
             - delay: 1s

  - platform: gpio
    pin:
      number: GPIO35
      mode: INPUT
      id: fontana_switch
      inverted: True
    filters:
    - delayed_on: 50ms
    name: "Fontana Taster"
    on_press:
      then:
        - if: 
           condition:
             switch.is_off: fontana
           then:
             - switch.turn_on: fontana
             - delay: 1s
           else:
            - switch.turn_off: fontana
            - delay: 1s

  - platform: gpio
    pin:
      number: GPIO13
      mode:
        input: true
        pullup: true
      inverted: true
    filters:
    - delayed_on: 50ms
    name: "Fasada Splana Taster"
    id: button_fasada_spalna
    on_press:
      then:
        - if:
           condition: 
             light.is_off: fasada_spalna
           then:
             - light.turn_on: 
                id: "fasada_spalna"
           else:
             - light.turn_off: fasada_spalna
        - delay: 1s

#  - platform: gpio
#    pin:
#      number: 15
#      mode: INPUT_PULLUP
#      inverted: True
#    name: "Button 3"
#    filters:
#    - delayed_on: 50ms
#    internal: True
#    id: Switch_1_button     
#    on_click:
#      then:
#       - switch.toggle: "switch_1"
#       - delay: 1s
# 
#switch:
#  - platform: gpio
#    pin: 12
#    name: "Switch 1"
#    id: "switch_1"

    # this provides fr a possibility to rstart from the web console or Home automation should we ever need it
#  - platform: restart
#    name: "Restart"

output:
  - platform: gpio
    pin: GPIO32
    id: radio
    inverted: true
  - platform: gpio
    pin: GPIO33
    id: fasada_kupatilo
    inverted: true
  - platform: ledc
    pin: GPIO22
    frequency: 2441 Hz #2000 Hz promeneto
    id: pwm_w1
  - platform: gpio
    pin: GPIO26
    id: light_fasada_spalna
    inverted: true

light:
  - platform: binary
    name: "Fasada Svetilki Spalna"
    output: light_fasada_spalna
    id: fasada_spalna
  - platform: binary
    name: "Radio"
    output: radio
    id: light_radio
    icon: "mdi:speaker-wireless"
  - platform: binary
    name: "Fasada Kupatilo Svetilki"
    output: fasada_kupatilo
    id: light_fasada_kupatilo
  - platform: monochromatic
    name: "Tenda"
    output: pwm_w1
    gamma_correct: 2.0
    id: tenda_led

switch:
  - platform: gpio
    pin: GPIO25
    inverted: true
    id: fontana
    icon: "mdi:fountain"
    name: "Fontana"
[18:10:39][D][main:165]: while loop, dim=48, brightness=0.3400, step=0.0200, max=1.0000, gamma=2.0000
[18:10:39][D][light:035]: 'Tenda' Setting:
[18:10:39][D][light:050]:   Brightness: 32%
[18:10:39][D][light:084]:   Transition length: 0.1s
[18:10:40][D][main:165]: while loop, dim=48, brightness=0.3200, step=0.0200, max=1.0000, gamma=2.0000
[18:10:40][D][light:035]: 'Tenda' Setting:
[18:10:40][D][light:050]:   Brightness: 30%
[18:10:40][D][light:084]:   Transition length: 0.1s
[18:10:40][D][binary_sensor:036]: 'Tenda Taster': Sending state OFF
[18:10:40][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[18:10:40][V][binary_sensor.automation:035]: Multi Click: action not started because first level does not match!
[18:10:40][V][binary_sensor.automation:062]: C i=1 min=500
[18:10:40][V][binary_sensor.automation:101]: Multi Click: Hooray, multi click is valid. Triggering!
[18:10:40][D][main:152]: pijachuva ili stishuva
[18:10:46][D][binary_sensor:036]: 'Tenda Taster': Sending state ON
[18:10:46][V][binary_sensor.automation:025]: START min=0 max=1000
[18:10:46][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[18:10:46][V][binary_sensor.automation:025]: START min=0 max=1000
[18:10:46][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[18:10:46][V][binary_sensor.automation:025]: START min=2000 max=4294967294
[18:10:46][V][binary_sensor.automation:026]: Multi Click: Starting multi click action!
[18:10:46][V][component:199]: Component gpio.binary_sensor took a long time for an operation (0.06 s).
[18:10:46][V][component:200]: Components should block for at most 20-30ms.
[18:10:46][D][binary_sensor:036]: 'Tenda Taster': Sending state OFF
[18:10:46][V][binary_sensor.automation:054]: A i=1 min=0 max=1000
[18:10:46][V][binary_sensor.automation:062]: C i=1 min=500
[18:10:46][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[18:10:46][V][binary_sensor.automation:101]: Multi Click: Hooray, multi click is valid. Triggering!
[18:10:46][D][main:130]: on_multi_click: pali ili gasi eden stisok
[18:10:46][D][light:035]: 'Tenda' Setting:
[18:10:46][D][light:046]:   State: OFF
[18:10:46][D][light:084]:   Transition length: 1.0s
[18:10:47][V][binary_sensor.automation:095]: Multi Click: You waited too long to PRESS.
[18:10:47][V][binary_sensor.automation:071]: Multi Click: Invalid length of press, starting cooldown of 1000 ms...
[18:10:47][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[18:10:48][V][binary_sensor.automation:074]: Multi Click: Cooldown ended, matching is now enabled again.
[18:11:27][D][esp32.preferences:114]: Saving preferences to flash...