Skip to content

Commit

Permalink
Ensure screenlogic retries if the protocol adapter is still booting (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
bdraco authored Dec 18, 2024
1 parent e73512e commit 9bff9c5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 2 deletions.
3 changes: 2 additions & 1 deletion homeassistant/components/screenlogic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Any

from screenlogicpy import ScreenLogicError, ScreenLogicGateway
from screenlogicpy.const.common import ScreenLogicConnectionError
from screenlogicpy.const.data import SHARED_VALUES

from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -64,7 +65,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ScreenLogicConfigEntry)
try:
await gateway.async_connect(**connect_info)
await gateway.async_update()
except ScreenLogicError as ex:
except (ScreenLogicConnectionError, ScreenLogicError) as ex:
raise ConfigEntryNotReady(ex.msg) from ex

coordinator = ScreenlogicDataUpdateCoordinator(
Expand Down
36 changes: 35 additions & 1 deletion tests/components/screenlogic/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
from unittest.mock import DEFAULT, patch

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.number import DOMAIN as NUMBER_DOMAIN
from homeassistant.components.screenlogic import DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.util import slugify
Expand Down Expand Up @@ -284,3 +286,35 @@ def stub_connect(*args, **kwargs):

for entity_id in tested_entity_ids:
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

0 comments on commit 9bff9c5

Please sign in to comment.