home-assistant / frontend

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

"select" erroneously updates on UI reconnect #21459

Open carrel-gr opened 3 months ago

carrel-gr commented 3 months ago

Checklist

Describe the issue you are experiencing

If the UI disconnects while displaying a "select" sensor entity, then when it reconnects, it can erroneously update that entity with stale data.

The issue arises with my MQTT auto-discovered device. It has a "select" sensor entity so that either the device can change the state or the UI can. When the UI is connected, this all works correctly. However, IF I have a UI page open that displays this "select" entity, and then I put that browser tab in the background, then after 5 minutes (as per profile settings) the UI will disconnect. Then IF the device (not the UI) changes the state, and following that I reopen the tab that shows the "select", the UI will update the entity state with the old/stale UI data.

Of note: I also have a "box" sensor entity and this does NOT have this issue. On reconnect, the box entity is properly updated with the latest device state (which was delivered via MQTT). The UI does not send old/state UI state to the device.

Also of note: If the entity state doesn't change, then when the UI reconnects, the UI does NOT attempt to send an update. So it does appear that the UI is indeed reading the new device state (via MQTT). However, when the device state and the UI state are not equal, it is erroneously choosing to update the device's entity state to the older/stale UI state.

Also, if I put the UI tab in the background for less than 5 minutes (so it doesn't disconnect) then this issue doesn't happen. Instead, when the device updates the entity state (via MQTT) the UI simply notices the change and updates its state appropriately.

Also, if the select entity is NOT currently being displayed in a tab, then there are no problems switching to a page that shows the select entity. (And disconnecting or not disconnecting makes no difference to this.)

I see this in chrome tabs as well as in the Android app.

Describe the behavior you expected

The UI should not send old/stale state for a "select" entity to a device on UI reconnect.

Steps to reproduce the issue

  1. Create a "select" entity for a MQTT device with a state_topic and command_topic so the state can be changed either by the device or the select element in the UI. (This might also be an issue for non-MQTT entities, but I don't know.)
  2. In Profile Settings->Browser Settings, make sure it is set to auto-disconnect after 5 minutes.
  3. Have the "select" UI entity showing on a browser page/tab.
  4. Switch to any other browser tab and wait 5 minutes for the UI to disconnect.
  5. without using the UI, change the entity state to something else. (Ensure the device properly informs the MQTT broker.)
  6. Switch to the tab from step 3 above which shows the "select" entity.
  7. You will then see the command_topic used to update the device with the old/stale UI state for that "select" entity. ...

What version of Home Assistant Core has the issue?

2024.7.3

What was the last working version of Home Assistant Core?

No response

In which browser are you experiencing the issue with?

Google Chrome 126.0.6478.183

Which operating system are you using to run this browser?

macOS Sonoma 14.5

State of relevant entities

No response

Problem-relevant frontend configuration

The entity is autodiscovered by MQTT.
In the MQTT topic: homeassistant/select/A2M-AL9876543210987/A2M_Test/config
there is the following JSON:

{
  "component": "select",
  "device": {
    "name": "A2M-AL9876543210987",
    "model": "FAKE-BAT",
    "manufacturer": "AlphaESS",
    "identifiers": [
      "A2M-AL9876543210987"
    ]
  },
  "name": "A2M Test",
  "unique_id": "A2M-AL9876543210987_A2M_Test",
  "device_class": "enum",
  "options": [
    "One",
    "Two",
    "Three"
  ],
  "state_topic": "Alpha2MQTT/A2M-AL9876543210987/A2M_Test/state",
  "command_topic": "Alpha2MQTT/A2M-AL9876543210987/A2M_Test/command",
  "availability_topic": "Alpha2MQTT/A2M-AL9876543210987/status"
}

Javascript errors shown in your browser console/inspector

none

Additional information

The issue was discussed in the forums in this post: https://community.home-assistant.io/t/is-this-a-bug-with-select/752416

There is a somewhat useful screenshot there as well as further descriptions.

karwosts commented 3 months ago

I can reproduce this with select.speed entity from the demo integration, so it's not really got anything to do with MQTT.

It looks like on disconnect/reconnect the entire device page is torn down and recreated, and the first updated pass of a mwc select entity fires a valueChanged event when populating the initial value of the combobox. Then we pick this up and pass it on to call the service to change the entity value.

Might be a tricky bug to fix.

github-actions[bot] commented 3 weeks 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.

carrel-gr commented 3 weeks ago

I can verify that this issue still exists. It reproduces every time for me. I am on the latest release.

Also I think this should be considered as a more significant issue. This causes random changes in system settings without making it obvious that things have changed. In my case, the Operating Mode of my Energy Storage System has a "select" entity. My automations change the mode according to schedule. However, if I leave a HA page open which shows the select and an automation runs while the page is disconnected, then when I return to that page my ESS mode will be erroneously set to a stale value. This can be bad. And we really don't want HA to be the culprit that mysteriously/erroneously changes system values. Thanks!!

esand commented 2 weeks ago

It looks like on disconnect/reconnect the entire device page is torn down and recreated, and the first updated pass of a mwc select entity fires a valueChanged event when populating the initial value of the combobox. Then we pick this up and pass it on to call the service to change the entity value.

Might be a tricky bug to fix.

I don't know Python, but I do know JS and might be able to help - can you link to where in the source all of this happens? If it's using regular browser JS events, you should be able to do something to differentiate between user and browser initiated event calls and not fire valueChanged when populating the select list. At the very least I can take a look.

karwosts commented 2 weeks ago

I'm not exactly sure but it's maybe from src/components/ha-select.ts which is an extension of MWC Select

esand commented 2 weeks ago

I'm not exactly sure but it's maybe from src/components/ha-select.ts which is an extension of MWC Select

I believe you're correct. I think the issue starts at https://github.com/home-assistant/frontend/blob/42df951f895f9a6f2ff961eacaaa4b2dc696eeda/src/components/ha-select.ts#L54 which would detect the select has a value, making it then go on to set valueSetDirectly to true.

esand commented 2 weeks ago

I'm not very familiar with TypeScript, however I think that _clearValue is bound to the click event, which should mean that it could be extended to take in the Event object which would be passed to it. If that's the case, you can check Event.isTrusted (https://developer.mozilla.org/en-US/docs/Web/API/Event/isTrusted) which should be a boolean that would indicate if it was user-generated, or script generated. I would assume (possibly naively) that it should be false when the UI is re-rendered.