Fix some yeelights showing wrong state after on/off (#55279)

This commit is contained in:
J. Nick Koston 2021-08-26 13:25:26 -05:00 committed by GitHub
parent 089dfad78a
commit ae1d2926cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 3 deletions

View File

@ -692,10 +692,10 @@ class YeelightDevice:
else:
self._name = self._host # Default name is host
async def async_update(self):
async def async_update(self, force=False):
"""Update device properties and send data updated signal."""
if self._initialized and self._available:
# No need to poll, already connected
if not force and self._initialized and self._available:
# No need to poll unless force, already connected
return
await self._async_update_properties()
async_dispatcher_send(self._hass, DATA_UPDATED.format(self._host))

View File

@ -762,6 +762,10 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
_LOGGER.error("Unable to set the defaults: %s", ex)
return
# Some devices (mainly nightlights) will not send back the on state so we need to force a refresh
if not self.is_on:
await self.device.async_update(True)
async def async_turn_off(self, **kwargs) -> None:
"""Turn off."""
if not self.is_on:
@ -772,6 +776,9 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
duration = int(kwargs.get(ATTR_TRANSITION) * 1000) # kwarg in s
await self.device.async_turn_off(duration=duration, light_type=self.light_type)
# Some devices will not send back the off state so we need to force a refresh
if self.is_on:
await self.device.async_update(True)
async def async_set_mode(self, mode: str):
"""Set a power mode."""

View File

@ -1122,3 +1122,59 @@ async def test_effects(hass: HomeAssistant):
for name, target in effects.items():
await _async_test_effect(name, target)
await _async_test_effect("not_existed", called=False)
async def test_state_fails_to_update_triggers_update(hass: HomeAssistant):
"""Ensure we call async_get_properties if the turn on/off fails to update the state."""
mocked_bulb = _mocked_bulb()
properties = {**PROPERTIES}
properties.pop("active_mode")
properties["color_mode"] = "3" # HSV
mocked_bulb.last_properties = properties
mocked_bulb.bulb_type = BulbType.Color
config_entry = MockConfigEntry(
domain=DOMAIN, data={**CONFIG_ENTRY_DATA, CONF_NIGHTLIGHT_SWITCH: False}
)
config_entry.add_to_hass(hass)
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# We use asyncio.create_task now to avoid
# blocking starting so we need to block again
await hass.async_block_till_done()
mocked_bulb.last_properties["power"] = "off"
await hass.services.async_call(
"light",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: ENTITY_LIGHT,
},
blocking=True,
)
assert len(mocked_bulb.async_turn_on.mock_calls) == 1
assert len(mocked_bulb.async_get_properties.mock_calls) == 2
mocked_bulb.last_properties["power"] = "on"
await hass.services.async_call(
"light",
SERVICE_TURN_OFF,
{
ATTR_ENTITY_ID: ENTITY_LIGHT,
},
blocking=True,
)
assert len(mocked_bulb.async_turn_off.mock_calls) == 1
assert len(mocked_bulb.async_get_properties.mock_calls) == 3
# But if the state is correct no calls
await hass.services.async_call(
"light",
SERVICE_TURN_ON,
{
ATTR_ENTITY_ID: ENTITY_LIGHT,
},
blocking=True,
)
assert len(mocked_bulb.async_turn_on.mock_calls) == 1
assert len(mocked_bulb.async_get_properties.mock_calls) == 3