Retry yeelight setup later if first update fails (#58446)

pull/58570/head
J. Nick Koston 2021-10-27 03:09:45 -05:00 committed by GitHub
parent 58b6b5854d
commit 4653d0b079
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 10 deletions

View File

@ -80,7 +80,7 @@ SSDP_TARGET = ("239.255.255.250", 1982)
SSDP_ST = "wifi_bulb"
DISCOVERY_ATTEMPTS = 3
DISCOVERY_SEARCH_INTERVAL = timedelta(seconds=2)
DISCOVERY_TIMEOUT = 2
DISCOVERY_TIMEOUT = 8
YEELIGHT_RGB_TRANSITION = "RGBTransition"
@ -211,9 +211,6 @@ async def _async_initialize(
data={**entry.data, CONF_DETECTED_MODEL: device.capabilities["model"]},
)
# fetch initial state
await device.async_update()
@callback
def _async_normalize_config_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
@ -500,7 +497,6 @@ class YeelightDevice:
self._device_type = None
self._available = True
self._initialized = False
self._did_first_update = False
self._name = None
@property
@ -568,7 +564,7 @@ class YeelightDevice:
@property
def is_color_flow_enabled(self) -> bool:
"""Return true / false if color flow is currently running."""
return int(self._color_flow) == ACTIVE_COLOR_FLOWING
return self._color_flow and int(self._color_flow) == ACTIVE_COLOR_FLOWING
@property
def _active_mode(self):
@ -632,7 +628,6 @@ class YeelightDevice:
async def async_update(self, force=False):
"""Update device properties and send data updated signal."""
self._did_first_update = True
if not force and self._initialized and self._available:
# No need to poll unless force, already connected
return
@ -649,7 +644,7 @@ class YeelightDevice:
was_available = self._available
self._available = data.get(KEY_CONNECTED, True)
if update_needs_bg_power_workaround(data) or (
self._did_first_update and not was_available and self._available
not was_available and self._available
):
# On reconnect the properties may be out of sync
#
@ -724,4 +719,20 @@ async def _async_get_device(
)
entry.async_on_unload(_async_stop_listen_on_unload)
# fetch initial state
await device.async_update()
if (
# Must have last_properties
not device.bulb.last_properties
# Must have at least a power property
or (
"main_power" not in device.bulb.last_properties
and "power" not in device.bulb.last_properties
)
):
raise ConfigEntryNotReady(
"Could not fetch initial state; try power cycling the device"
)
return device

View File

@ -488,7 +488,7 @@ class YeelightGenericLight(YeelightEntity, LightEntity):
brightness_property = (
"bright" if self._bulb.music_mode else self._brightness_property
)
brightness = self._get_property(brightness_property)
brightness = self._get_property(brightness_property) or 0
return round(255 * (int(brightness) / 100))
@property

View File

@ -380,6 +380,34 @@ async def test_async_listen_error_late_discovery(hass, caplog):
assert config_entry.data[CONF_DETECTED_MODEL] == MODEL
async def test_fail_to_fetch_initial_state(hass, caplog):
"""Test failing to fetch initial state results in a retry."""
config_entry = MockConfigEntry(
domain=DOMAIN, data={CONF_HOST: IP_ADDRESS, **CONFIG_ENTRY_DATA}
)
config_entry.add_to_hass(hass)
mocked_bulb = _mocked_bulb()
del mocked_bulb.last_properties["power"]
del mocked_bulb.last_properties["main_power"]
with _patch_discovery(), patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.SETUP_RETRY
await hass.async_block_till_done()
assert "Could not fetch initial state; try power cycling the device" in caplog.text
with _patch_discovery(), patch(f"{MODULE}.AsyncBulb", return_value=_mocked_bulb()):
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=5))
await hass.async_block_till_done()
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=10))
await hass.async_block_till_done()
assert config_entry.state is ConfigEntryState.LOADED
async def test_unload_before_discovery(hass, caplog):
"""Test unloading before discovery."""
config_entry = MockConfigEntry(domain=DOMAIN, data=CONFIG_ENTRY_DATA)

View File

@ -751,7 +751,7 @@ async def test_device_types(hass: HomeAssistant, caplog):
mocked_bulb.last_properties = properties
async def _async_setup(config_entry):
with patch(f"{MODULE}.AsyncBulb", return_value=mocked_bulb):
with _patch_discovery(), 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