Use correct state for emulated_hue covers (#106516)
This commit is contained in:
parent
b8ddd61b26
commit
50acf85f48
2 changed files with 38 additions and 4 deletions
|
@ -57,6 +57,7 @@ from homeassistant.const import (
|
||||||
SERVICE_TURN_OFF,
|
SERVICE_TURN_OFF,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
SERVICE_VOLUME_SET,
|
SERVICE_VOLUME_SET,
|
||||||
|
STATE_CLOSED,
|
||||||
STATE_OFF,
|
STATE_OFF,
|
||||||
STATE_ON,
|
STATE_ON,
|
||||||
STATE_UNAVAILABLE,
|
STATE_UNAVAILABLE,
|
||||||
|
@ -73,6 +74,7 @@ from homeassistant.util.network import is_local
|
||||||
from .config import Config
|
from .config import Config
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
_OFF_STATES: dict[str, str] = {cover.DOMAIN: STATE_CLOSED}
|
||||||
|
|
||||||
# How long to wait for a state change to happen
|
# How long to wait for a state change to happen
|
||||||
STATE_CHANGE_WAIT_TIMEOUT = 5.0
|
STATE_CHANGE_WAIT_TIMEOUT = 5.0
|
||||||
|
@ -394,7 +396,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
||||||
return self.json_message("Bad request", HTTPStatus.BAD_REQUEST)
|
return self.json_message("Bad request", HTTPStatus.BAD_REQUEST)
|
||||||
parsed[STATE_ON] = request_json[HUE_API_STATE_ON]
|
parsed[STATE_ON] = request_json[HUE_API_STATE_ON]
|
||||||
else:
|
else:
|
||||||
parsed[STATE_ON] = entity.state != STATE_OFF
|
parsed[STATE_ON] = _hass_to_hue_state(entity)
|
||||||
|
|
||||||
for key, attr in (
|
for key, attr in (
|
||||||
(HUE_API_STATE_BRI, STATE_BRIGHTNESS),
|
(HUE_API_STATE_BRI, STATE_BRIGHTNESS),
|
||||||
|
@ -585,7 +587,7 @@ class HueOneLightChangeView(HomeAssistantView):
|
||||||
)
|
)
|
||||||
|
|
||||||
if service is not None:
|
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.async_create_task(
|
||||||
hass.services.async_call(domain, service, data, blocking=True)
|
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
|
cached_state = entry_state
|
||||||
elif time.time() - entry_time < STATE_CACHED_TIMEOUT and entry_state[
|
elif time.time() - entry_time < STATE_CACHED_TIMEOUT and entry_state[
|
||||||
STATE_ON
|
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
|
# 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.
|
# is in sync so that it can be detected as an error by Alexa.
|
||||||
cached_state = entry_state
|
cached_state = entry_state
|
||||||
|
@ -676,7 +678,7 @@ def get_entity_state_dict(config: Config, entity: State) -> dict[str, Any]:
|
||||||
@lru_cache(maxsize=512)
|
@lru_cache(maxsize=512)
|
||||||
def _build_entity_state_dict(entity: State) -> dict[str, Any]:
|
def _build_entity_state_dict(entity: State) -> dict[str, Any]:
|
||||||
"""Build a state dict for an entity."""
|
"""Build a state dict for an entity."""
|
||||||
is_on = entity.state != STATE_OFF
|
is_on = _hass_to_hue_state(entity)
|
||||||
data: dict[str, Any] = {
|
data: dict[str, Any] = {
|
||||||
STATE_ON: is_on,
|
STATE_ON: is_on,
|
||||||
STATE_BRIGHTNESS: None,
|
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))
|
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(
|
async def wait_for_state_change_or_timeout(
|
||||||
hass: core.HomeAssistant, entity_id: str, timeout: float
|
hass: core.HomeAssistant, entity_id: str, timeout: float
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
|
@ -1019,6 +1019,12 @@ async def test_set_position_cover(hass_hue, hue_client) -> None:
|
||||||
cover_test = hass_hue.states.get(cover_id)
|
cover_test = hass_hue.states.get(cover_id)
|
||||||
assert cover_test.state == "closed"
|
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
|
level = 20
|
||||||
brightness = round(level / 100 * 254)
|
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(
|
fan_json = await perform_get_light_state(
|
||||||
hue_client, "fan.living_room_fan", HTTPStatus.OK
|
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
|
assert round(fan_json["state"][HUE_API_STATE_BRI] * 100 / 254) == 33
|
||||||
|
|
||||||
await perform_put_light_state(
|
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(
|
fan_json = await perform_get_light_state(
|
||||||
hue_client, "fan.living_room_fan", HTTPStatus.OK
|
hue_client, "fan.living_room_fan", HTTPStatus.OK
|
||||||
)
|
)
|
||||||
|
assert fan_json["state"][HUE_API_STATE_ON] is True
|
||||||
assert (
|
assert (
|
||||||
round(fan_json["state"][HUE_API_STATE_BRI] * 100 / 254) == 66
|
round(fan_json["state"][HUE_API_STATE_BRI] * 100 / 254) == 66
|
||||||
) # small rounding error in inverse operation
|
) # 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(
|
fan_json = await perform_get_light_state(
|
||||||
hue_client, "fan.living_room_fan", HTTPStatus.OK
|
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
|
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:
|
async def test_put_with_form_urlencoded_content_type(hass_hue, hue_client) -> None:
|
||||||
"""Test the form with urlencoded content."""
|
"""Test the form with urlencoded content."""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue