home-assistant / frontend

:lollipop: Frontend for Home Assistant
https://demo.home-assistant.io
Other
3.98k stars 2.72k forks source link

Cover Button States #17945

Open wernerhp opened 1 year ago

wernerhp commented 1 year ago

Checklist

Describe the issue you are experiencing

The problem

Cover button states are not dependent on CoverOperation

COVER_OPERATION_IDLE

■ button state

■ button is always enabled (when stop_action is set) regardless of the cover state and operation (even when COVER_OPERATION_IDLE)

Cover Open image Cover Closed image

■ button is expected to be

Stop direction change

The cover stop direction should be configurable.
After stopping, covers may

COVER_OPERATION_OPENING / COVER_OPERATION_CLOSING

Instant operations

The current behaviour has the opposite direction enabled when the cover is opening or closing.

↑ button is enabled during COVER_OPERATION_CLOSING image

↓ button is enabled during COVER_OPERATION_OPENING image

Not all covers can instantly switch direction from opening to closing. A window blind may be able to go from opening to closing without stopping, but a garage door motors may first needs to stop before operating in the opposite direction.

↑ and ↓ buttons should be configurable to enable/disable instant operations.

↑ and ↓ buttons are expected to be

Describe the behavior you expected

■ button is expected to be

↑ and ↓ buttons are expected to be

Steps to reproduce the issue

View cover while opening/closing.

What version of Home Assistant Core has the issue?

2023.9.2

What was the last working version of Home Assistant Core?

No response

In which browser are you experiencing the issue with?

No response

Which operating system are you using to run this browser?

No response

State of relevant entities

Reported the issue to ESP Home, because I ran into the issue with the following yaml config, however it seems to be HA related.

Click to expand ```yaml binary_sensor: - platform: gpio pin: number: ${open_pin} inverted: true mode: input: true pullup: true id: cover_open internal: true name: "Cover Open" filters: delayed_on_off: 50ms on_state: lambda: |- if (id(cover_open).state && !id(cover_closed).state) { id(garage_door).position = cover::COVER_OPEN; id(garage_door).current_operation = CoverOperation::COVER_OPERATION_IDLE; id(garage_door).publish_state(); id(status).publish_state("Open"); } else if (!id(cover_open).state && !id(cover_closed).state) { if (id(garage_door).position == cover::COVER_OPEN) { id(garage_door).current_operation = CoverOperation::COVER_OPERATION_CLOSING; id(garage_door).publish_state(); id(status).publish_state("Closing"); } else if (id(garage_door).position == cover::COVER_CLOSED) { id(garage_door).current_operation = CoverOperation::COVER_OPERATION_OPENING; id(garage_door).publish_state(); id(status).publish_state("Opening"); } } else if (!id(cover_open).state && id(cover_closed).state) { id(garage_door).position = cover::COVER_CLOSED; id(garage_door).current_operation = CoverOperation::COVER_OPERATION_IDLE; id(garage_door).publish_state(); id(status).publish_state("Closed"); } - platform: gpio pin: number: ${closed_pin} inverted: true mode: input: true pullup: true id: cover_closed internal: true name: "Cover Closed" filters: delayed_on_off: 50ms on_state: lambda: |- if (id(cover_open).state && !id(cover_closed).state) { id(garage_door).position = cover::COVER_OPEN; id(garage_door).current_operation = CoverOperation::COVER_OPERATION_IDLE; id(garage_door).publish_state(); id(status).publish_state("Open"); } else if (!id(cover_open).state && !id(cover_closed).state) { if (id(garage_door).position == cover::COVER_OPEN) { id(garage_door).current_operation = CoverOperation::COVER_OPERATION_CLOSING; id(garage_door).publish_state(); id(status).publish_state("Closing"); } else if (id(garage_door).position == cover::COVER_CLOSED) { id(garage_door).current_operation = CoverOperation::COVER_OPERATION_OPENING; id(garage_door).publish_state(); id(status).publish_state("Opening"); } } else if (!id(cover_open).state && id(cover_closed).state) { id(garage_door).position = cover::COVER_CLOSED; id(garage_door).current_operation = CoverOperation::COVER_OPERATION_IDLE; id(garage_door).publish_state(); id(status).publish_state("Closed"); } output: - platform: gpio pin: number: ${relay_1_pin} inverted: false id: relay_1 button: - platform: output output: relay_1 id: button_1 disabled_by_default: true duration: 500ms name: "Button 1" icon: "mdi:gesture-tap-button" cover: - platform: template name: "Garage Door" device_class: garage id: garage_door open_action: - button.press: button_1 close_action: - button.press: button_1 stop_action: - button.press: button_1 optimistic: false text_sensor: - platform: template icon: mdi:information-outline id: status name: "Status" disabled_by_default: true

Problem-relevant frontend configuration

No response

Javascript errors shown in your browser console/inspector

No response

Additional information

No response

hahn23 commented 1 year ago

Hi,

I looked at your yaml config and can't see an real usability of your if/if else contruction in the binary_sensor part.

Isn't an "Endstop Cover" the exact right thing you need? https://esphome.io/components/cover/endstop

With that, you wouldn't have to bother with those if else state publishing at all.

Did I get this right: Your garage door has just one relay contact and you can switch between open stop and close by pushing the button several times? And you have two endstop contacts that will trigger either on open or closed stages?

Than you should think of using endstop cover instead. To get an quite good state response you just would have to measure one closing and one opening of the door and add the measured times into your yaml. After that it will use those times to always show an calculated state.

For example I used something similar and when viewing the device in HA and it is for example open. Than the state will show 100% when clicking "closing" it will decrease to 0% and while it's doing that, it operates in an "idle" state.

All that aside, I can't realy make real sense out of using an garage door with just 1 button and 1 relay output. I only know such doors with seperate relays for opening and closing...

wernerhp commented 1 year ago

@hahn23 I'm not questioning the yaml config or the functioning of my relay. I shared that for context. The issue is the state of the three cover buttons on lovelace.

To answer your question, the door has one relay and two binary sensors. The endstop cover doesn't work the way I need. My understanding of the endstop cover is that the relay is triggered whenever the endstop is reached. In my scenario the binary sensors are not used to control the door. They are purely to determine the state of the door.

The lambda on the twobinary_sensor is used to set the position and operation of the cover as well as determine the state of the door and set an additional status text_sensor. This sensor shows either Open, Opening, Closed, Closed (come to think of it I can add Stopped).

Back to the door motor... Every time you press the button on the remote, it triggers the relay which starts/stops the motor. The motor changes direction every time it stops. i.e. open - stop - close - stop etc. as described in the issue above

↓ ■ ↑ ■ ↓ ■ ↑ / continue in the opposite direction

other motors work differently and continue in the same direction until fully closed

↓ ■ ↓ ■ ↓ ■ ↓ / continue in the same direction

The relay and sensors work perfectly fine.

The problem is that while the cover is in one state, e.g. OPERATION_IDLE and OPEN, the UI still shows the stop ■ button as enabled. Since the door is IDLE the stop button should be disabled, because you can't stop an idle door.

Similarly, when the door is OPERATION_OPENING, the open ↑ button remains enabled. This doesn't make sense and the open ↑ button should be disabled while the cover is OPERATION_OPENING. You can't make the door open while it's already opening and pressing it again will make the door stop, which is counter-intuitive.

It's expected that only the stop ■ button be enabled when the OPERATION_OPENING and OPERATION_CLOSING. Once the door is IDLE, only the button for the opposite direction from the last operation should be enabled. i.e. if I was opening and then stop, then I expect only ↓ to be enabled.

maaaruuu commented 11 months ago

@wernerhp Thanks for the original post, I have the exact same situation with the garage door so while searching for a solution I found your post and ended up using most of your code. However, you were missing the logic to figure out the OPERATION_OPENING and OPERATION_CLOSING if you stop the door in the mid-operation and reverse it. To address this I have expanded your code by adding some additional on_press lambdas at the button_1. I needed to add an additional text sensor to store previous state if the door gets stopped mid-operation but now the door also tracks the current_operation on every command.

However, I still have the same problem as you where I would like to address the buttons in HA so only the correct commands are enabled.

Have you ever found any solution or workaround?

...
button:
  - platform: output
    output: garage_door_relay
    id: button_1
    disabled_by_default: true
    duration: 500ms
    name: "Button 1"
    icon: "mdi:gesture-tap-button"
    on_press:
      lambda: |-
        if (id(garage_door).current_operation == CoverOperation::COVER_OPERATION_CLOSING) {
          id(past_state).publish_state("COVER_OPERATION_CLOSING");
          id(garage_door).current_operation = CoverOperation::COVER_OPERATION_IDLE;
        } else if (id(garage_door).current_operation == CoverOperation::COVER_OPERATION_OPENING) {
          id(past_state).publish_state("COVER_OPERATION_OPENING");
          id(garage_door).current_operation = CoverOperation::COVER_OPERATION_IDLE;
        } else if (id(garage_door).current_operation == CoverOperation::COVER_OPERATION_IDLE) {
          if (id(past_state).state == "COVER_OPERATION_CLOSING") {
            id(past_state).publish_state("COVER_OPERATION_IDLE");
            id(garage_door).current_operation = CoverOperation::COVER_OPERATION_OPENING;
          } else if (id(past_state).state == "COVER_OPERATION_OPENING") {
            id(past_state).publish_state("COVER_OPERATION_IDLE");
            id(garage_door).current_operation = CoverOperation::COVER_OPERATION_CLOSING;
            }
        }

cover:
  - platform: template
    name: "Garage Door"
    device_class: garage
    id: garage_door
    open_action:
      - button.press: button_1
    close_action:
      - button.press: button_1
    stop_action:
      - button.press: button_1
    optimistic: false

text_sensor:
  - platform: template
    icon: mdi:information-outline
    id: status
    name: "Status"
    disabled_by_default: true
  - platform: template
    icon: mdi:information-outline
    id: past_state
    name: "Past status"
    disabled_by_default: true
wernerhp commented 11 months ago

No workaround, no, which is why I logged this issue. Hopefully someone from the team can have a look.

github-actions[bot] commented 8 months ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest Home Assistant version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

wernerhp commented 8 months ago

.

github-actions[bot] commented 5 months ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest Home Assistant version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

wernerhp commented 5 months ago

Still open.

SkateWarp commented 5 months ago

I'm having this exact issue.

github-actions[bot] commented 2 months ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest Home Assistant version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

wernerhp commented 1 month ago

Still a problem