My Garage Door: I have cover states Open, Opening, Closing and Closed using a D1 Mini and two reed switches plus a WS2812 LED strip indicating parking position

Post your whole config. Binary sensors as well

Iā€™d like to point out that I also donā€™t want inferred endstops as then the cover would appear to be fully open/closed after the opening/closing duration completes but I might have stopped it midway or it hit an obstacle and reversed.

Hereā€™s the config as it stands now:

esphome:
  name: my-garage-door
  friendly_name: My Garage Door

esp8266:
  board: d1_mini
  restore_from_flash: True

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "<redacted"

ota:
  password: "<redacted>"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Distance-Sensor Fallback Hotspot"
    password: "<redacted>"

captive_portal:

light:
  - platform: neopixelbus
    variant: WS2812
    pin: D8
    num_leds: 20
    type: rgb
    name: "Parking Light Indicator"
    id: parking_light_indicator
    restore_mode: ALWAYS_OFF

sensor:
  - platform: ultrasonic
    name: 'parking_sensor'
    id: parking_sensor
    trigger_pin: D1
    echo_pin: D2
    unit_of_measurement: "m"
    accuracy_decimals: 1
    update_interval: 1s
    timeout: 4.0m
    pulse_time: 10us
    filters:
      - or:
          - throttle: 30s
          - delta: 5%
    on_value:
      then: 
        - if: 
            # turn light off when door closed 
            condition:
              - binary_sensor.is_on:
                  id: closed_contact_sensor
            then:
              light.turn_off:
                id: parking_light_indicator

        - if: 
            # Show RED first
            condition:
              and:
                - lambda: 'return id(parking_sensor).state < id(red_trigger_level).state;'
                - binary_sensor.is_on:
                    id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 0%
                blue: 0%        
        - if: 
            # show YELLOW if getting close to correct spot 
            condition:
              and:
                - lambda: 'return id(parking_sensor).state < id(yellow_trigger_level).state;'
                - binary_sensor.is_on:
                    id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                # yellow
                red: 100%
                green: 100%
                blue: 0%
        - if: 
            # Show GREEN when in right spot
            condition:
              and:
                - lambda: 'return id(parking_sensor).state < id(green_trigger_level).state;'
                - binary_sensor.is_on:
                    id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 80%
                red: 0%
                green: 100%
                blue: 0%

  - platform: homeassistant
    name: "Red Trigger Level"
    id: "red_trigger_level"
    entity_id: input_number.red_trigger_level

  - platform: homeassistant
    name: "Yellow Trigger Level"
    id: "yellow_trigger_level"
    entity_id: input_number.yellow_trigger_level

  - platform: homeassistant
    name: "Green Trigger Level"
    id: "green_trigger_level"
    entity_id: input_number.green_trigger_level

# Binary sensors to check if door is open or closed
binary_sensor:
# Vehicle Presence
  - platform: template
    name: Vehicle
    device_class: presence
    lambda:
      if (id(parking_sensor).state < id(yellow_trigger_level).state) {
        return true;
      } else {
        return false;
      }

  - platform: gpio
    pin:
      number: D5
      mode: INPUT_PULLUP
      inverted: True
    name: "Open Contact Sensor"
    id: open_contact_sensor
    internal: False
#    on_press:
#      - cover.template.publish:
#          id: template_cover
#          state: OPEN
#          current_operation: IDLE
#    on_release:
#      - cover.template.publish:
#          id: template_cover
#          current_operation: CLOSING

  - platform: template
    name: "Open Movement Sensor"
    id: open_movement_sensor
    lambda:
      if (id(closed_contact_sensor).state) {
        return false;
      } else {
        return true;
      }
    
  - platform: gpio
    pin:
      number: D6
      mode: INPUT_PULLUP
      inverted: True
    name: "Closed Contact Sensor"
    id: closed_contact_sensor
    internal: False
#    on_press:
#      - cover.template.publish:
#          id: template_cov
#          state: CLOSED
#          current_operation: IDLE
#    on_release:
#      - cover.template.publish:
#          id: template_cov
#          current_operation: OPENING

  - platform: template
    name: "Close Movement Sensor"
    id: close_movement_sensor
    lambda:
      if (id(open_contact_sensor).state) {
        return false;
      } else {
        return true;
      }
    
# This creates the actual garage door in HA. The state is based on two contact sensors. 
cover:
  - platform: feedback
    name: "Garage Door"
    id: endstop_cover
    device_class: garage
    has_built_in_endstop: true

    open_action:
      - switch.turn_on: relay
    open_duration: 10s
    open_endstop: open_contact_sensor
#    open_sensor: open_movement_sensor

    close_action:
      - switch.turn_on: relay
    close_duration: 10s
    close_endstop: closed_contact_sensor
#    close_sensor: close_movement_sensor

    stop_action:
      - switch.turn_on: relay

#cover:
#  - platform: template
#    device_class: garage
#    name: "Garage Door"
#    id: template_cover
#    has_position: True
#    lambda: |-
#      if (id(contact_sensor_open).state) {
#        return COVER_OPEN;
#      } else  {
#        if (id(contact_sensor_closed).state) {
#          return COVER_CLOSED;
#        } else {
#          return {};
#        }
#      }
#    ## Can I disable this action if current operation is OPENING?
#    open_action:
#      - switch.turn_on: relay
#
#    ## Can I disable this action if current_operation is CLOSING?
#    close_action:
#      - switch.turn_on: relay
#
#    ## Can I disable this action if state is OPEN or CLOSED?
#    stop_action:
#      - switch.turn_on: relay
# Relay Switch to send the pulse to the garage door opener button

switch:
  - platform: gpio
    pin: D7
    name: "Garage Door Relay"
    id: relay
    internal: False
    # Toggle the relay with a 0.5s pulse simulating a manual button press
    on_turn_on:
    - delay : 500ms
    - switch.turn_off: relay
    ## To-do
    # If id(contact_sensor_closed).state) == off AND id(contact_sensor_open).state) == off AND template_cov.current_operation is CLOSING
    # Then 
    # cover.template.publish:
    #   id:template_cov
    #   current_operation: OPENING
    #   state: CLOSED

    # If id(contact_sensor_closed).state) == off AND id(contact_sensor_open).state) == off AND template_cov.current_operation is OPENING
    # Then 
    # cover.template.publish:
    #   id:template_cov
    #   current_operation: IDLE
    #   state: OPEN

Are both end_stops wired the same way? Youā€™re using NO on both?

Iā€™m using the two reed switches that come with OpenGarage

take the ā€œinvertedā€ off the bottom/closed reed switch. I donā€™t fully understand this but itā€™s what you need to do. It has something to do with like, the bottom being On/Closed and the top/Open and one needs to be on while the other is offā€¦ I reallyt cant explain it, just try it.

- platform: gpio
    pin:
      number: D6
      mode: INPUT_PULLUP
      inverted: False
    name: "Closed Contact Sensor"
    id: closed_contact_sensor
    internal: False

Here is mine if it helps. You dont need the Text_sensor, I just use it so I can get the door state elsewhere in HA without having to use the cover over and over.

cover:
  - platform: feedback
    name: "Overhead"
    id: overhead_2
    has_built_in_endstop: true
    max_duration: 17s
    open_action:
      - switch.toggle: cover_switch
      - text_sensor.template.publish:
         id: template_text
         state: "Opening"      
    open_duration: 16s
    open_endstop: top_reed_switch
    
    #open_sensor: open_movement_binary_sensor

    close_action:
      - switch.toggle: cover_switch
      - text_sensor.template.publish:
          id: template_text
          state: "Closing"
    close_duration: 16s
    close_endstop: bot_reed_switch
    
    #close_sensor: close_movement_binary_sensor

    stop_action:
      - switch.turn_on: cover_switch
      - text_sensor.template.publish:
         id: template_text
         state: "Stopped/Idle"         


button:
  - platform: restart
    name: "Barn Sensors Restart"
  - platform: safe_mode
    name: "Barn Sensors (Safe Mode)"  

binary_sensor:
  - platform: gpio
    pin: 
      number: D1 
      mode: INPUT_PULLUP
      inverted: true
    id: top_reed_switch
    name: "top reed"    
   # filters: 
     # delayed_on: 16s
    on_state:
      if:
        condition:
           binary_sensor.is_on: top_reed_switch
        then:
          - text_sensor.template.publish:
              id: template_text
              state: "Open" 
       

   
  - platform: gpio
    pin: 
      number: D5
      mode: INPUT_PULLUP
     # inverted: true
    id: bot_reed_switch
    name: "Bottom Reed"
   # filters: 
    #  delayed_off: 16s
    on_state:
      if:
        condition:
           binary_sensor.is_on: bot_reed_switch
        then:
          - text_sensor.template.publish:
              id: template_text
              state: "Closed"

You definately are doing it right by testing on a workbench! My garage
door was one of my first Esphome projects a couple years ago. I was so antsy to do it and just threw sensor and stuff up there. Ofcourse it didnā€™t work right and itā€™s a pain in @ss trying to troubleshoot stuff when itā€™s installed and even more so when it takes a ladder to get to it.

Something else to think aboutā€¦

You can use the Shelly 2.5 and hook it to your garage door opener. It has 2 inputs that allow you to track current. So you can see when there is current passing through the motor and distinguish between Up/Down and best of all It sees when the door is triggered by HA, the wall button. car remotes, or the obstacle/laser sensor. Itā€™s probably the most accurate way to track a door.

1 Like

With your logic, I do not see opening/closing when operating the door outside of HA, only when opening/closing within HA. Additionally, the closed contact sensor logic is backwards now and it only shows Closed when I remove the magnet from the bottom sensor after Iā€™ve introduced it.

Righy. When you trigger the door outside of HA, its outside of HA, so thats to be expected. Did you remove the movement sensors? Lets try to get the basic functions working first.

How many contacts are on the reed switch? It should say on them NO, COM, NC. How are you wiring them? Are they both the same?

The reed switches are just two wire on/off and each are NO.
With a movement sensor defined as the inverse of the opposing contact sensor, I can detect opening/closing external to HA and the cover states behave correctly in HA:
Door open switch = on & Door closed switch = off: Open
Door open switch = off & Door closed switch =off: Closing %
Door open switch = off & Door closed switch =on: Closed
Door open switch = off & Door closed switch =off: Opening %
Door open switch = on & Door closed switch =off: Open
or
Door open switch = off & Door closed switch =on: Closed
Door open switch = off & Door closed switch =off: Opening %
Door open switch = on & Door closed switch =off: Open
Door open switch = off & Door closed switch =off: Closing %
Door open switch = off & Door closed switch =on: Closed
or
Door open switch = on & Door closed switch = off: Open
Door open switch = off & Door closed switch =off: Closing %
Door open switch = on & Door closed switch =off: Open
or
Door open switch = off & Door closed switch =on: Closed
Door open switch = off & Door closed switch =off: Opening %
Door open switch = off & Door closed switch =on: Closed

The key element was setting has_built_in_endstop: true so that the door motor switch was not activated when the cover presumed the door was open/closed which would have had adverse effects. But I do need the movement sensors for external feedbackā€¦

My latest work was this which changes how the light strip acts plus adds a pulse to the start of the ā€˜greenā€™ light when in range:

light:
  - platform: neopixelbus
    variant: WS2812
    pin: D8
    num_leds: 30
    type: grb
    name: "Parking Light Indicator"
    id: parking_light_indicator
    restore_mode: ALWAYS_OFF
    effects:
      - pulse:
          name: "Fast Pulse"
          transition_length: 50ms
          update_interval: 100ms
          min_brightness: 0%
          max_brightness: 100%

sensor:
  - platform: ultrasonic
    id: parking_sensor
    trigger_pin: D1
    echo_pin: D2
    unit_of_measurement: "m"
    accuracy_decimals: 1
    update_interval: 1s
    timeout: 4.0m
    pulse_time: 10us
    on_value_range:
      - above: 1.85
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 0%
                blue: 0%
      - below: 1.85
        above: 1.7
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 15%
                blue: 0%
      - below: 1.7
        above: 1.55
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 30%
                blue: 0%
      - below: 1.55
        above: 1.4
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 45%
                blue: 0%
      - below: 1.4
        above: 1.25
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 60%
                blue: 0%
      - below: 1.25
        above: 1.1
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 75%
                blue: 0%
      - below: 1.1
        above: 0.7
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 90%
                blue: 0%
      - below: 0.7
        above: 0.5
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              light.turn_on:
                id: parking_light_indicator
                brightness: 100%
                red: 100%
                green: 100%
                blue: 0%
      - below: 0.5
        then:
          if: 
            condition:
              binary_sensor.is_on:
                id: open_contact_sensor
            then:
              - light.turn_on:
                  id: parking_light_indicator
                  effect: Fast Pulse
                  brightness: 100%
                  red: 0%
                  green: 100%
                  blue: 0%
              - delay : 1s
              - light.turn_on:
                  id: parking_light_indicator
                  effect: none
                  brightness: 100%
                  red: 0%
                  green: 100%
                  blue: 0%

Plus I removed name: 'parking sensor'and filters: from the ultrasonic sensor and added a copy with a delta filter to reduce updates to HA:

  - platform: copy
    name: 'parking_sensor'
    source_id: parking_sensor
    filters:
      - delta: 0.05

Oh ok, so theyre the pre-wired ones? Im honestly not sure the best way to track the cover from external triggers. If you use the configurable movement sensors it will probably show you ā€œopening/closingā€ but your going to mess everything else up. Im not positive but, im pretty sure those movement_sensors are for actual sensors detecting movement and direction. They are for current covers where you would use the Analog threshold binary sensors sensing the motor current to detect movement, direction, and motor stop events.

The only thing i can think of if you must have opening/closing for external triggers is 1. Add an actual movement sensor like a current sensor or rotary encoder. 2. Your going to have to create some extra logic that watches for when an end_stop is On and then changes but not from the cover triggering it. So, door is Closed - closed endstop turns Off and cover != cover.open - then return Opening.

Have you considered just getting a Shelly2.5 instead? It has 2 channels for AC current monitoring and it has a switch/relay. This would do everything you want and do it really well.

Sorry i forgot i already mentioned the Shelly2.5

Thanks, I will definitively look at the Shelley 2.5!
On my bench, this is now working the way I want though.
Just added an on_boot setting:

esphome:
  name: my-garage-door
  friendly_name: My Garage Door
  on_boot:
    priority: 100 # Highest priority, ensures light turns off without delay.
    then:
      - light.turn_off:
          id: parking_light_indicator

How is it handling external triggers?

Anything that opens the door outside HA (even manually opening it) triggers closed > opening > open (& vice-versa) via the movement sensors being inverse of the contact sensors.

But only if it starts at the open or closed endstop, right? Thats pretty much the reason i never took mine any further. If you open the door from the wall switch and then stoo it, the cover doesnt know you stppped it and it continues to show Opening untill the time limit is reached and i think it shows 99% open even if you stopped it 10" from closed position.

All this talking about garage doors has got me wanting to put a current sensor on mine and track it perfect in every situation. Ive got 1 CT clamp and gotta decide to get another one or scrap that and get a Shellyā€¦

Yes, the opening/closing is a timed event which proceeds to 1% / 99% even if the door was stopped halfway by the wall switch. Without a current sensor on the motor or a real position tracking device thereā€™s no way for the cover to know the exact state of the door between open & closed.

I finally have my WS2812 based LED bar w/30 LEDs working now.
Here are two videos: one of actual operation on my desk and the other is screen recording of the device in HA
Hereā€™s the yaml:

esphome:
  name: my-garage-door
  friendly_name: My Garage Door
  on_boot:
    priority: 100
    then:
      - binary_sensor.template.publish:
          id: open_movement_sensor
          state: False
      - binary_sensor.template.publish:
          id: close_movement_sensor
          state: False
      - if: 
          condition:
            binary_sensor.is_on:
              id: open_contact_sensor
          then:
            light.turn_on:
              id: parking_light_indicator
              effect: Slow Pulse
              brightness: 100%
              red: 100%
              green: 0%
              blue: 0%
        
esp8266:
  board: d1_mini
  restore_from_flash: True

logger:

api:
  encryption:
    key: "<redacted>"

ota:
  password: "<redacted>"

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

  ap:
    ssid: "Distance-Sensor Fallback Hotspot"
    password: "<redacted>"

captive_portal:

binary_sensor:
  - platform: template
    name: Vehicle
    device_class: presence
    lambda:
      if (id(parking_sensor).state < id(yellow_trigger_level).state) {
        return true;
      } else {
        return false;
      }

  - platform: gpio
    pin:
      number: D5
      mode: INPUT_PULLUP
      inverted: True
    name: "is Open"
    id: open_contact_sensor
    disabled_by_default: True
    internal: False
    on_press:
      - then:
        - binary_sensor.template.publish:
            id: open_movement_sensor
            state: False
        - binary_sensor.template.publish:
            id: close_movement_sensor
            state: False
      - then:
        - light.turn_on:
            id: parking_light_indicator
            effect: Slow Pulse
            brightness: 50%
            red: 100%
            green: 0%
            blue: 0%

    on_release:
      - binary_sensor.template.publish:
          id: close_movement_sensor
          state: True

  - platform: template
    name: "is Opening"
    id: open_movement_sensor
    disabled_by_default: True
    on_press:
      - light.turn_on:
          id: parking_light_indicator
          effect: Slow Pulse
          brightness: 100%
          red: 0%
          green: 0%
          blue: 100%
    
  - platform: gpio
    pin:
      number: D6
      mode: INPUT_PULLUP
      inverted: True
    name: "is Closed"
    id: closed_contact_sensor
    disabled_by_default: True
    internal: False
    on_press:
      then:
        - sensor.duty_time.stop: parking_light_duty_time
        - light.turn_off:
            id: parking_light_indicator
        - binary_sensor.template.publish:
            id: open_movement_sensor
            state: False
        - binary_sensor.template.publish:
            id: close_movement_sensor
            state: False
    on_release:
      - sensor.duty_time.reset: parking_light_duty_time
      - binary_sensor.template.publish:
          id: open_movement_sensor
          state: True

  - platform: template
    name: "is Closing"
    id: close_movement_sensor
    disabled_by_default: True
    on_press:
      then:
        - light.turn_on:
            id: parking_light_indicator
            effect: Slow Pulse
            brightness: 100%
            red: 85%
            green: 25%
            blue: 100%

cover:
  - platform: feedback
    name: "Garage Door"
    id: endstop_cover
    device_class: garage
    has_built_in_endstop: True
    max_duration: 12s

    open_action:
      - switch.turn_on: relay
    open_duration: 10s
    open_endstop: open_contact_sensor
    open_sensor: open_movement_sensor

    close_action:
      - switch.turn_on: relay
    close_duration: 10s
    close_endstop: closed_contact_sensor
    close_sensor: close_movement_sensor

    stop_action:
      - switch.turn_on: relay

light:
  - platform: neopixelbus
    variant: WS2812
    pin: D8
    num_leds: 30
    type: grb
    name: "Parking Light Indicator"
    id: parking_light_indicator
    restore_mode: ALWAYS_OFF
    effects:
      - pulse:
          name: "Slow Pulse"
          transition_length: 500ms
          update_interval: 750ms
          min_brightness: 0%
          max_brightness: 100%
      - pulse:
          name: "Fast Pulse"
          transition_length: 50ms
          update_interval: 100ms
          min_brightness: 0%
          max_brightness: 100%

sensor:
  - platform: duty_time
    id: parking_light_duty_time
    name: Parking Light Duty Time
    update_interval: 1s
    lambda: "return id(closed_contact_sensor).state == false;"
    restore: false
    last_time:
      name: Parking Light Last Turn-On Time
    on_value_range:
      above: 60
      then:
        - light.turn_off: parking_light_indicator
        - sensor.duty_time.stop: parking_light_duty_time

  - platform: ultrasonic
    id: parking_sensor
    trigger_pin: D1
    echo_pin: D2
    unit_of_measurement: "m"
    accuracy_decimals: 1
    update_interval: 1s
    timeout: 4.0m
    pulse_time: 10us
    filters:
      - delta: .02
    on_value:
      then:
        - if:
            condition:
              - binary_sensor.is_on: open_contact_sensor
              - sensor.duty_time.is_running: parking_light_duty_time
            then:
              - if:
                  condition:
                    lambda: |-
                      return id(red_trigger_level).state < id(parking_sensor).state;
                  then:
                    - light.turn_on:
                        id: parking_light_indicator
                        effect: Slow Pulse
                        brightness: 100%
                        red: 100%
                        green: 0%
                        blue: 0%
              - if:
                  condition:
                    lambda: |-
                      return (id(green_trigger_level).state < id(parking_sensor).state && id(parking_sensor).state < id(red_trigger_level).state);
                  then:
                    - light.turn_on:
                        id: parking_light_indicator
                        effect: none
                        brightness: 100%
                        red: !lambda |-
                          return ((id(parking_sensor).state - id(green_trigger_level).state) / (id(red_trigger_level).state - id(green_trigger_level).state));
                        green: !lambda |-
                          return ((id(red_trigger_level).state - id(parking_sensor).state) / (id(red_trigger_level).state - id(green_trigger_level).state));
                        blue: 0%
              - if:
                  condition:
                    lambda: |-
                      return  id(parking_sensor).state < id(green_trigger_level).state;
                  then:
                    - light.turn_on:
                        id: parking_light_indicator
                        effect: Fast Pulse
                        brightness: 100%
                        red: 0%
                        green: 100%
                        blue: 0%
                    - delay : 1s
                    - light.turn_on:
                        id: parking_light_indicator
                        effect: none
                        brightness: 100%
                        red: 0%
                        green: 100%
                        blue: 0%

  - platform: copy
    name: 'parking_sensor'
    source_id: parking_sensor
    filters:
      - delta: 0.05

  - platform: homeassistant
    name: "Red Trigger Level"
    id: "red_trigger_level"
    entity_id: input_number.red_trigger_level

  - platform: homeassistant
    name: "Yellow Trigger Level"
    id: "yellow_trigger_level"
    entity_id: input_number.yellow_trigger_level

  - platform: homeassistant
    name: "Green Trigger Level"
    id: "green_trigger_level"
    entity_id: input_number.green_trigger_level

switch:
  - platform: gpio
    pin: D7
    name: "Garage Door Relay"
    id: relay
    internal: False
    # Toggle the relay with a 0.5s pulse simulating a manual button press
    on_turn_on:
    - delay : 500ms
    - switch.turn_off: relay

time:
  - platform: sntp
    id: my_time

Note the duty_time sensor to turn off the light after a fixed time period after opening is case I leave the door open for an extended period. I am going to do more testing before boxing it up an installing it but itā€™s coming along nicely I think, finally!
Oh, here are the trigger level input numbers:

image

My new automation in HAā€¦

image

alias: My Garage Door - "Stalled"
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.my_garage_door_is_closing
      - binary_sensor.my_garage_door_is_opening
    for:
      hours: 0
      minutes: 0
      seconds: 20
    to: "on"
condition: []
action:
  - service: python_script.hass_entities
    data:
      action: set_state
      entity_id: cover.my_garage_door_garage_door
      state: Stalled
  - service: python_script.hass_entities
    data:
      action: delete_attribute
      entity_id: cover.my_garage_door_garage_door
      attribute: current_position
mode: single

I changed my mindā€¦

image

alias: My Garage Door - "Stalled"
description: ""
trigger:
  - platform: state
    entity_id:
      - binary_sensor.my_garage_door_is_closing
    for:
      hours: 0
      minutes: 0
      seconds: 20
    to: "on"
    id: Closing
  - platform: state
    entity_id:
      - binary_sensor.my_garage_door_is_opening
    for:
      hours: 0
      minutes: 0
      seconds: 20
    to: "on"
    id: Opening
condition: []
action:
  - service: python_script.hass_entities
    data:
      action: delete_attribute
      entity_id: cover.my_garage_door_garage_door
      attribute: current_position
  - choose:
      - conditions:
          - condition: trigger
            id:
              - Closing
        sequence:
          - service: python_script.hass_entities
            data:
              action: set_state
              entity_id: cover.my_garage_door_garage_door
              state: Partially Closed
      - conditions:
          - condition: trigger
            id:
              - Opening
        sequence:
          - service: python_script.hass_entities
            data:
              action: set_state
              entity_id: cover.my_garage_door_garage_door
              state: Partially Open
mode: single

I like the way you have this layed out, it looks good and very configurable.

I dont use the wall switch, i mostly use HA or the RF remote in the cars which the cover doesnt track either. I recently bought a 4 channel RF relay board really just to play with but, it gave me the idea to ditch the car RF remotes and use these these keychain RF transmitters. Each remote, the RF codes are different too so, i can tell which remote was used to trigger something or use the extra ones for something elseā€¦ i couldnt find any modules with an esp board and rf receiver but a receiver could easily be added to one.

Thanks for the compliment. I rarely use the wall switch either and mostly use HA to open/close the door via car is leaving automation based on my phone connecting to car bluetooth & BT status update via HA companion app, car is in garage via the existing OpenGarage distance sensor and activation via MIMOlite Z-Wave momentary switch wired in parallel with wall switch, and arrival automation triggered by GPS location tracking arriving home, garage is empty & MIMOlite opening it. When my phone then disconnects from car bluetooth, the garage Alexa Echo asks if she should close the garage door, I say yes and she activates the MIMOlite to close the door.