Fix optimistic covers (#149962)

This commit is contained in:
Petro31
2025-08-04 07:35:13 -04:00
committed by GitHub
parent 46cfdddc80
commit e2bc73f153
3 changed files with 27 additions and 3 deletions

View File

@@ -216,6 +216,7 @@ class AbstractTemplateCover(AbstractTemplateEntity, CoverEntity):
_entity_id_format = ENTITY_ID_FORMAT
_optimistic_entity = True
_extra_optimistic_options = (CONF_POSITION,)
# The super init is not called because TemplateEntity and TriggerEntity will call AbstractTemplateEntity.__init__.
# This ensures that the __init__ on AbstractTemplateEntity is not called twice.

View File

@@ -20,6 +20,7 @@ class AbstractTemplateEntity(Entity):
_entity_id_format: str
_optimistic_entity: bool = False
_extra_optimistic_options: tuple[str, ...] | None = None
_template: Template | None = None
def __init__(
@@ -35,9 +36,14 @@ class AbstractTemplateEntity(Entity):
if self._optimistic_entity:
self._template = config.get(CONF_STATE)
self._attr_assumed_state = self._template is None or config.get(
CONF_OPTIMISTIC, False
)
optimistic = self._template is None
if self._extra_optimistic_options:
optimistic = optimistic and all(
config.get(option) is None
for option in self._extra_optimistic_options
)
self._attr_assumed_state = optimistic or config.get(CONF_OPTIMISTIC, False)
if (object_id := config.get(CONF_OBJECT_ID)) is not None:
self.entity_id = async_generate_entity_id(

View File

@@ -239,6 +239,7 @@ async def setup_position_cover(
{
TEST_OBJECT_ID: {
**COVER_ACTIONS,
"set_cover_position": SET_COVER_POSITION,
"position_template": position_template,
}
},
@@ -249,6 +250,7 @@ async def setup_position_cover(
count,
{
**NAMED_COVER_ACTIONS,
"set_cover_position": SET_COVER_POSITION,
"position": position_template,
},
)
@@ -258,6 +260,7 @@ async def setup_position_cover(
count,
{
**NAMED_COVER_ACTIONS,
"set_cover_position": SET_COVER_POSITION,
"position": position_template,
},
)
@@ -565,6 +568,7 @@ async def test_template_position(
position: int | None,
expected: str,
caplog: pytest.LogCaptureFixture,
calls: list[ServiceCall],
) -> None:
"""Test the position_template attribute."""
hass.states.async_set(TEST_STATE_ENTITY_ID, CoverState.OPEN)
@@ -580,6 +584,19 @@ async def test_template_position(
assert state.state == expected
assert "ValueError" not in caplog.text
# Test to make sure optimistic is not set with only a position template.
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_SET_COVER_POSITION,
{ATTR_ENTITY_ID: TEST_ENTITY_ID, "position": 10},
blocking=True,
)
await hass.async_block_till_done()
state = hass.states.get(TEST_ENTITY_ID)
assert state.attributes.get("current_position") == position
assert state.state == expected
@pytest.mark.parametrize("count", [1])
@pytest.mark.parametrize(