Use correct state for emulated_hue covers (#106516)

This commit is contained in:
Thomas Hollstegge 2023-12-28 20:30:26 +01:00 committed by Bram Kragten
parent b8ddd61b26
commit 50acf85f48
2 changed files with 38 additions and 4 deletions

View file

@ -57,6 +57,7 @@ from homeassistant.const import (
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
SERVICE_VOLUME_SET,
STATE_CLOSED,
STATE_OFF,
STATE_ON,
STATE_UNAVAILABLE,
@ -73,6 +74,7 @@ from homeassistant.util.network import is_local
from .config import Config
_LOGGER = logging.getLogger(__name__)
_OFF_STATES: dict[str, str] = {cover.DOMAIN: STATE_CLOSED}
# How long to wait for a state change to happen
STATE_CHANGE_WAIT_TIMEOUT = 5.0
@ -394,7 +396,7 @@ class HueOneLightChangeView(HomeAssistantView):
return self.json_message("Bad request", HTTPStatus.BAD_REQUEST)
parsed[STATE_ON] = request_json[HUE_API_STATE_ON]
else:
parsed[STATE_ON] = entity.state != STATE_OFF
parsed[STATE_ON] = _hass_to_hue_state(entity)
for key, attr in (
(HUE_API_STATE_BRI, STATE_BRIGHTNESS),
@ -585,7 +587,7 @@ class HueOneLightChangeView(HomeAssistantView):
)
if service is not None:
state_will_change = parsed[STATE_ON] != (entity.state != STATE_OFF)
state_will_change = parsed[STATE_ON] != _hass_to_hue_state(entity)
hass.async_create_task(
hass.services.async_call(domain, service, data, blocking=True)
@ -643,7 +645,7 @@ def get_entity_state_dict(config: Config, entity: State) -> dict[str, Any]:
cached_state = entry_state
elif time.time() - entry_time < STATE_CACHED_TIMEOUT and entry_state[
STATE_ON
] == (entity.state != STATE_OFF):
] == _hass_to_hue_state(entity):
# We only want to use the cache if the actual state of the entity
# is in sync so that it can be detected as an error by Alexa.
cached_state = entry_state
@ -676,7 +678,7 @@ def get_entity_state_dict(config: Config, entity: State) -> dict[str, Any]:
@lru_cache(maxsize=512)
def _build_entity_state_dict(entity: State) -> dict[str, Any]:
"""Build a state dict for an entity."""
is_on = entity.state != STATE_OFF
is_on = _hass_to_hue_state(entity)
data: dict[str, Any] = {
STATE_ON: is_on,
STATE_BRIGHTNESS: None,
@ -891,6 +893,11 @@ def hass_to_hue_brightness(value: int) -> int:
return max(1, round((value / 255) * HUE_API_STATE_BRI_MAX))
def _hass_to_hue_state(entity: State) -> bool:
"""Convert hass entity states to simple True/False on/off state for Hue."""
return entity.state != _OFF_STATES.get(entity.domain, STATE_OFF)
async def wait_for_state_change_or_timeout(
hass: core.HomeAssistant, entity_id: str, timeout: float
) -> None:

View file

@ -1019,6 +1019,12 @@ async def test_set_position_cover(hass_hue, hue_client) -> None:
cover_test = hass_hue.states.get(cover_id)
assert cover_test.state == "closed"
cover_json = await perform_get_light_state(
hue_client, "cover.living_room_window", HTTPStatus.OK
)
assert cover_json["state"][HUE_API_STATE_ON] is False
assert cover_json["state"][HUE_API_STATE_BRI] == 1
level = 20
brightness = round(level / 100 * 254)
@ -1095,6 +1101,7 @@ async def test_put_light_state_fan(hass_hue, hue_client) -> None:
fan_json = await perform_get_light_state(
hue_client, "fan.living_room_fan", HTTPStatus.OK
)
assert fan_json["state"][HUE_API_STATE_ON] is True
assert round(fan_json["state"][HUE_API_STATE_BRI] * 100 / 254) == 33
await perform_put_light_state(
@ -1112,6 +1119,7 @@ async def test_put_light_state_fan(hass_hue, hue_client) -> None:
fan_json = await perform_get_light_state(
hue_client, "fan.living_room_fan", HTTPStatus.OK
)
assert fan_json["state"][HUE_API_STATE_ON] is True
assert (
round(fan_json["state"][HUE_API_STATE_BRI] * 100 / 254) == 66
) # small rounding error in inverse operation
@ -1132,8 +1140,27 @@ async def test_put_light_state_fan(hass_hue, hue_client) -> None:
fan_json = await perform_get_light_state(
hue_client, "fan.living_room_fan", HTTPStatus.OK
)
assert fan_json["state"][HUE_API_STATE_ON] is True
assert round(fan_json["state"][HUE_API_STATE_BRI] * 100 / 254) == 100
await perform_put_light_state(
hass_hue,
hue_client,
"fan.living_room_fan",
False,
brightness=0,
)
assert (
hass_hue.states.get("fan.living_room_fan").attributes[fan.ATTR_PERCENTAGE] == 0
)
with patch.object(hue_api, "STATE_CACHED_TIMEOUT", 0.000001):
await asyncio.sleep(0.000001)
fan_json = await perform_get_light_state(
hue_client, "fan.living_room_fan", HTTPStatus.OK
)
assert fan_json["state"][HUE_API_STATE_ON] is False
assert fan_json["state"][HUE_API_STATE_BRI] == 1
async def test_put_with_form_urlencoded_content_type(hass_hue, hue_client) -> None:
"""Test the form with urlencoded content."""