Retry yeelight setup later if first update fails (#58446)
parent
58b6b5854d
commit
4653d0b079
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue