Set state of entity with invalid state to unknown (#99452)

* Set state of entity with invalid state to unknown

* Add test

* Apply suggestions from code review

Co-authored-by: Robert Resch <robert@resch.dev>

* Update test_entity.py

---------

Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
Erik Montnemery 2023-09-04 14:09:51 +02:00 committed by Bram Kragten
parent bdc39e1d52
commit e5fd6961a8
2 changed files with 42 additions and 2 deletions

View File

@ -35,7 +35,11 @@ from homeassistant.const import (
EntityCategory, EntityCategory,
) )
from homeassistant.core import CALLBACK_TYPE, Context, HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, Context, HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError, NoEntitySpecifiedError from homeassistant.exceptions import (
HomeAssistantError,
InvalidStateError,
NoEntitySpecifiedError,
)
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.util import dt as dt_util, ensure_unique_string, slugify from homeassistant.util import dt as dt_util, ensure_unique_string, slugify
@ -848,7 +852,15 @@ class Entity(ABC):
self._context = None self._context = None
self._context_set = None self._context_set = None
hass.states.async_set(entity_id, state, attr, self.force_update, self._context) try:
hass.states.async_set(
entity_id, state, attr, self.force_update, self._context
)
except InvalidStateError:
_LOGGER.exception("Failed to set state, fall back to %s", STATE_UNKNOWN)
hass.states.async_set(
entity_id, STATE_UNKNOWN, {}, self.force_update, self._context
)
def schedule_update_ha_state(self, force_refresh: bool = False) -> None: def schedule_update_ha_state(self, force_refresh: bool = False) -> None:
"""Schedule an update ha state change task. """Schedule an update ha state change task.

View File

@ -3,6 +3,7 @@ import asyncio
from collections.abc import Iterable from collections.abc import Iterable
import dataclasses import dataclasses
from datetime import timedelta from datetime import timedelta
import logging
import threading import threading
from typing import Any from typing import Any
from unittest.mock import MagicMock, PropertyMock, patch from unittest.mock import MagicMock, PropertyMock, patch
@ -1477,3 +1478,30 @@ async def test_warn_no_platform(
caplog.clear() caplog.clear()
ent.async_write_ha_state() ent.async_write_ha_state()
assert error_message not in caplog.text assert error_message not in caplog.text
async def test_invalid_state(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
) -> None:
"""Test the entity helper catches InvalidState and sets state to unknown."""
ent = entity.Entity()
ent.entity_id = "test.test"
ent.hass = hass
ent._attr_state = "x" * 255
ent.async_write_ha_state()
assert hass.states.get("test.test").state == "x" * 255
caplog.clear()
ent._attr_state = "x" * 256
ent.async_write_ha_state()
assert hass.states.get("test.test").state == STATE_UNKNOWN
assert (
"homeassistant.helpers.entity",
logging.ERROR,
f"Failed to set state, fall back to {STATE_UNKNOWN}",
) in caplog.record_tuples
ent._attr_state = "x" * 255
ent.async_write_ha_state()
assert hass.states.get("test.test").state == "x" * 255