Turn on/ Turn off always toggles switch regardless of state

Hello,

My daughter has one of those mirrors with lights around the edge, and a touch button in the mirror. I wanted to make it controllable (as a learning thing) so I connected an esp8266 to a servo (which touches the back of the button) and a light sensor (inside the mirror) to register if the lights are on or off.

All works well, except when I do a turn off or turn on (from HA), it always toggles it, regardless of whether the switch is shown as on or off.

Have I done something stupid. Code below:

esp8266:
  board: nodemcuv2

output:
  - platform: esp8266_pwm
    id: pwm_output
    frequency: 50Hz
    pin: D8

servo:
  - id: my_servo
    output: pwm_output

i2c:

sensor:
  - platform: bh1750
    id: mirror_brightness
    name: "Mirror Test Brightness"
    update_interval: 10s

switch:
  - platform: template
    name: "Dummy Light"
    optimistic: true
    lambda: |-
      if ((id(mirror_brightness).state) > 0.2) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
      - servo.write:
          id: my_servo
          level: -55.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -45.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -60.0%

    turn_off_action:
      - servo.write:
          id: my_servo
          level: -55.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -42.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -60.0%
  - platform: restart
    name: "Mirror ESP Restart"

The light sensor only reads every 10s so there is a short delay before the status updates in HA, but it does update.

I don’t see the switch config? I don’t see how you can control the servo from HA using the posted code tbh.

I would try and force an update of the light sensor, wait a second and then test whether to report the switch as on/off.

Something along these lines:

sensor:
  - platform: bh1750
    id: mirror_brightness
    name: "Mirror Test Brightness"
    update_interval: 10s

switch:
  - platform: template
    name: "Dummy Light"
    id: light_switch
    turn_on_action:
      - servo.write:
          id: my_servo
          level: -55.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -45.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -60.0%
      - lambda: |-
          id(mirror_brightness).update();
      - delay: 1s
      - if:
          condition:
            lambda: 'return id(mirror_brightness).state > 0.2;'
          then:
            - switch.template.publish:
                id: light_switch
                state: ON
    turn_off_action:
      - servo.write:
          id: my_servo
          level: -55.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -42.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -60.0%
      - lambda: |-
          id(mirror_brightness).update();
      - delay: 1s
      - if:
          condition:
            lambda: 'return id(mirror_brightness).state <= 0.2;'
          then:
            - switch.template.publish:
                id: light_switch
                state: OFF

button:
  - platform: restart
    name: "Mirror ESP Restart"

Thanks, yes the switch: was missing because of a cut and paste error.

I’ll give that a go thanks.

Or they could just simply turn on Optimistic mode…

  • optimistic (Optional, boolean): Whether to operate in optimistic mode - when in this mode, any command sent to the template switch will immediately update the reported state. Defaults to false.

The problem is with the servo. There are 3 seperate movements for each turn_on and turn_off and each one does the exact same servo movements. Theres no difference between On and Off

Optimistic would always turn the switch on, no matter if the servo worked or not. I’m guessing he wants confirmation, hence the light sensor.

Well that has cut the response time down of the light, so that is better, but still seems to always toggle, rather than turn on or off.

I did have optimistic mode turned on, and it didn’t help.

Optimistic just keeps the switch states updated between HA and esphome.

Why is the servo making 3 movements with 3 delays for each turn_on and turn_off?

What do the logs say? Whats triggering the toggle?

Where is the automation for the light sensor? Is that causing a problem? We cant tell because you didnt post it.

What type of switch/button is on the mirror? Is it a momentary switch or latching?

Why are you even using a servo? Why not connect to the button and then you can trigger it from esp and also read its state if someone physically pushes it. Servo seems kind of over the top and unnecessary.

Try to define lambda to determine switch state:

switch:
  - platform: template
    name: "Dummy Light"
    id: light_switch
    optimistic: false
    lambda: return id(mirror_brightness).state > 0.2;
    . . . 

May be this will make it faster can also add update for light sensor:

    lambda: |-
      id(mirror_brightness).update();
      return id(mirror_brightness).state > 0.2;

Or just change update_interval on light sensor.

1 Like

I like @Masterzz suggestion.

Anyway, since the switch actions are identical, maybe move it to a script, so as not to duplicate too much code?

...
    turn_on_action:
      - script.execute: activate_servo
    turn_off_action:
      - script.execute: activate_servo
 ...

 script:
  - id: activate_servo
    mode: single
    then:
      - servo.write:
          id: my_servo
          level: -55.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -42.0%
      - delay: 500ms
      - servo.write:
          id: my_servo
          level: -60.0%