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.
```

* coverage
pull/133096/head^2
J. Nick Koston 2024-12-17 18:57:43 -07:00 committed by GitHub
parent e73512e11c
commit 9bff9c5e7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 37 additions and 2 deletions

View File

@ -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(

View File

@ -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