Ensure screenlogic retries if the protocol adapter is still booting (#133444)
* Ensure screenlogic retries if the protocol adapter is still booting If the protocol adapter is still booting, it will disconnect and never retry ``` Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/config_entries.py", line 640, in __async_setup_with_context result = await component.async_setup_entry(hass, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/screenlogic/__init__.py", line 65, in async_setup_entry await gateway.async_connect(**connect_info) File "/usr/local/lib/python3.13/site-packages/screenlogicpy/gateway.py", line 142, in async_connect connectPkg = await async_connect_to_gateway( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...<4 lines>... ) ^ File "/usr/local/lib/python3.13/site-packages/screenlogicpy/requests/login.py", line 107, in async_connect_to_gateway mac_address = await async_gateway_connect(transport, protocol, max_retries) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.13/site-packages/screenlogicpy/requests/login.py", line 77, in async_gateway_connect raise ScreenLogicConnectionError("Host unexpectedly disconnected.") screenlogicpy.const.common.ScreenLogicConnectionError: Host unexpectedly disconnected. ``` * coveragepull/133096/head^2
parent
e73512e11c
commit
9bff9c5e7b
|
@ -4,6 +4,7 @@ import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from screenlogicpy import ScreenLogicError, ScreenLogicGateway
|
from screenlogicpy import ScreenLogicError, ScreenLogicGateway
|
||||||
|
from screenlogicpy.const.common import ScreenLogicConnectionError
|
||||||
from screenlogicpy.const.data import SHARED_VALUES
|
from screenlogicpy.const.data import SHARED_VALUES
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
@ -64,7 +65,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ScreenLogicConfigEntry)
|
||||||
try:
|
try:
|
||||||
await gateway.async_connect(**connect_info)
|
await gateway.async_connect(**connect_info)
|
||||||
await gateway.async_update()
|
await gateway.async_update()
|
||||||
except ScreenLogicError as ex:
|
except (ScreenLogicConnectionError, ScreenLogicError) as ex:
|
||||||
raise ConfigEntryNotReady(ex.msg) from ex
|
raise ConfigEntryNotReady(ex.msg) from ex
|
||||||
|
|
||||||
coordinator = ScreenlogicDataUpdateCoordinator(
|
coordinator = ScreenlogicDataUpdateCoordinator(
|
||||||
|
|
|
@ -4,12 +4,14 @@ from dataclasses import dataclass
|
||||||
from unittest.mock import DEFAULT, patch
|
from unittest.mock import DEFAULT, patch
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from screenlogicpy import ScreenLogicGateway
|
from screenlogicpy import ScreenLogicError, ScreenLogicGateway
|
||||||
|
from screenlogicpy.const.common import ScreenLogicConnectionError
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
||||||
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
|
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
|
||||||
from homeassistant.components.screenlogic import DOMAIN
|
from homeassistant.components.screenlogic import DOMAIN
|
||||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
@ -284,3 +286,35 @@ async def test_platform_setup(
|
||||||
|
|
||||||
for entity_id in tested_entity_ids:
|
for entity_id in tested_entity_ids:
|
||||||
assert hass.states.get(entity_id) is not None
|
assert hass.states.get(entity_id) is not None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"exception",
|
||||||
|
[ScreenLogicConnectionError, ScreenLogicError],
|
||||||
|
)
|
||||||
|
async def test_retry_on_connect_exception(
|
||||||
|
hass: HomeAssistant, mock_config_entry: MockConfigEntry, exception: Exception
|
||||||
|
) -> None:
|
||||||
|
"""Test setup retries on expected exceptions."""
|
||||||
|
|
||||||
|
def stub_connect(*args, **kwargs):
|
||||||
|
raise exception
|
||||||
|
|
||||||
|
mock_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch(
|
||||||
|
GATEWAY_DISCOVERY_IMPORT_PATH,
|
||||||
|
return_value={},
|
||||||
|
),
|
||||||
|
patch.multiple(
|
||||||
|
ScreenLogicGateway,
|
||||||
|
async_connect=stub_connect,
|
||||||
|
is_connected=False,
|
||||||
|
_async_connected_request=DEFAULT,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
assert not await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert mock_config_entry.state is ConfigEntryState.SETUP_RETRY
|
||||||
|
|
Loading…
Reference in New Issue