Clean up ElkM1 lib (#42319)
This commit is contained in:
parent
f8d87bff16
commit
cc77621477
6 changed files with 64 additions and 51 deletions
|
@ -249,18 +249,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
for keypad in elk.keypads: # pylint: disable=no-member
|
||||
keypad.add_callback(_element_changed)
|
||||
|
||||
if not await async_wait_for_elk_to_sync(elk, SYNC_TIMEOUT):
|
||||
_LOGGER.error(
|
||||
"Timed out after %d seconds while trying to sync with ElkM1 at %s",
|
||||
SYNC_TIMEOUT,
|
||||
conf[CONF_HOST],
|
||||
)
|
||||
elk.disconnect()
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
if elk.invalid_auth:
|
||||
_LOGGER.error("Authentication failed for ElkM1")
|
||||
return False
|
||||
try:
|
||||
if not await async_wait_for_elk_to_sync(elk, SYNC_TIMEOUT, conf[CONF_HOST]):
|
||||
return False
|
||||
except asyncio.TimeoutError as exc:
|
||||
raise ConfigEntryNotReady from exc
|
||||
|
||||
hass.data[DOMAIN][entry.entry_id] = {
|
||||
"elk": elk,
|
||||
|
@ -312,16 +305,40 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
return unload_ok
|
||||
|
||||
|
||||
async def async_wait_for_elk_to_sync(elk, timeout):
|
||||
"""Wait until the elk system has finished sync."""
|
||||
async def async_wait_for_elk_to_sync(elk, timeout, conf_host):
|
||||
"""Wait until the elk has finished sync. Can fail login or timeout."""
|
||||
|
||||
def login_status(succeeded):
|
||||
nonlocal success
|
||||
|
||||
success = succeeded
|
||||
if succeeded:
|
||||
_LOGGER.info("ElkM1 login succeeded.")
|
||||
else:
|
||||
elk.disconnect()
|
||||
_LOGGER.error("ElkM1 login failed; invalid username or password.")
|
||||
event.set()
|
||||
|
||||
def sync_complete():
|
||||
event.set()
|
||||
|
||||
success = True
|
||||
event = asyncio.Event()
|
||||
elk.add_handler("login", login_status)
|
||||
elk.add_handler("sync_complete", sync_complete)
|
||||
try:
|
||||
with async_timeout.timeout(timeout):
|
||||
await elk.sync_complete()
|
||||
return True
|
||||
await event.wait()
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.error(
|
||||
"Timed out after %d seconds while trying to sync with ElkM1 at %s",
|
||||
SYNC_TIMEOUT,
|
||||
conf_host,
|
||||
)
|
||||
elk.disconnect()
|
||||
raise
|
||||
|
||||
return False
|
||||
return success
|
||||
|
||||
|
||||
def _create_elk_services(hass):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
"""Config flow for Elk-M1 Control integration."""
|
||||
import asyncio
|
||||
import logging
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
@ -65,20 +66,7 @@ async def validate_input(data):
|
|||
)
|
||||
elk.connect()
|
||||
|
||||
timed_out = False
|
||||
if not await async_wait_for_elk_to_sync(elk, VALIDATE_TIMEOUT):
|
||||
_LOGGER.error(
|
||||
"Timed out after %d seconds while trying to sync with ElkM1 at %s",
|
||||
VALIDATE_TIMEOUT,
|
||||
url,
|
||||
)
|
||||
timed_out = True
|
||||
|
||||
elk.disconnect()
|
||||
|
||||
if timed_out:
|
||||
raise CannotConnect
|
||||
if elk.invalid_auth:
|
||||
if not await async_wait_for_elk_to_sync(elk, VALIDATE_TIMEOUT, url):
|
||||
raise InvalidAuth
|
||||
|
||||
device_name = data[CONF_PREFIX] if data[CONF_PREFIX] else "ElkM1"
|
||||
|
@ -116,7 +104,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
try:
|
||||
info = await validate_input(user_input)
|
||||
|
||||
except CannotConnect:
|
||||
except asyncio.TimeoutError:
|
||||
errors["base"] = "cannot_connect"
|
||||
except InvalidAuth:
|
||||
errors["base"] = "invalid_auth"
|
||||
|
@ -161,9 +149,5 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
return urlparse(url).hostname in existing_hosts
|
||||
|
||||
|
||||
class CannotConnect(exceptions.HomeAssistantError):
|
||||
"""Error to indicate we cannot connect."""
|
||||
|
||||
|
||||
class InvalidAuth(exceptions.HomeAssistantError):
|
||||
"""Error to indicate there is invalid auth."""
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"domain": "elkm1",
|
||||
"name": "Elk-M1 Control",
|
||||
"documentation": "https://www.home-assistant.io/integrations/elkm1",
|
||||
"requirements": ["elkm1-lib==0.8.4"],
|
||||
"requirements": ["elkm1-lib==0.8.5"],
|
||||
"codeowners": ["@gwww", "@bdraco"],
|
||||
"config_flow": true
|
||||
}
|
||||
|
|
|
@ -535,7 +535,7 @@ elgato==0.2.0
|
|||
eliqonline==1.2.2
|
||||
|
||||
# homeassistant.components.elkm1
|
||||
elkm1-lib==0.8.4
|
||||
elkm1-lib==0.8.5
|
||||
|
||||
# homeassistant.components.mobile_app
|
||||
emoji==0.5.4
|
||||
|
|
|
@ -278,7 +278,7 @@ eebrightbox==0.0.4
|
|||
elgato==0.2.0
|
||||
|
||||
# homeassistant.components.elkm1
|
||||
elkm1-lib==0.8.4
|
||||
elkm1-lib==0.8.5
|
||||
|
||||
# homeassistant.components.mobile_app
|
||||
emoji==0.5.4
|
||||
|
|
|
@ -3,14 +3,24 @@
|
|||
from homeassistant import config_entries, setup
|
||||
from homeassistant.components.elkm1.const import DOMAIN
|
||||
|
||||
from tests.async_mock import AsyncMock, MagicMock, PropertyMock, patch
|
||||
from tests.async_mock import MagicMock, patch
|
||||
|
||||
|
||||
def mock_elk(invalid_auth=None, sync_complete=None):
|
||||
"""Mock m1lib Elk."""
|
||||
|
||||
def handler_callbacks(type_, callback):
|
||||
nonlocal invalid_auth, sync_complete
|
||||
|
||||
if type_ == "login":
|
||||
if invalid_auth is not None:
|
||||
callback(not invalid_auth)
|
||||
elif type_ == "sync_complete":
|
||||
if sync_complete:
|
||||
callback()
|
||||
|
||||
mocked_elk = MagicMock()
|
||||
type(mocked_elk).invalid_auth = PropertyMock(return_value=invalid_auth)
|
||||
type(mocked_elk).sync_complete = AsyncMock()
|
||||
mocked_elk.add_handler.side_effect = handler_callbacks
|
||||
return mocked_elk
|
||||
|
||||
|
||||
|
@ -23,7 +33,7 @@ async def test_form_user_with_secure_elk(hass):
|
|||
assert result["type"] == "form"
|
||||
assert result["errors"] == {}
|
||||
|
||||
mocked_elk = mock_elk(invalid_auth=False)
|
||||
mocked_elk = mock_elk(invalid_auth=False, sync_complete=True)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.elkm1.config_flow.elkm1.Elk",
|
||||
|
@ -70,7 +80,7 @@ async def test_form_user_with_non_secure_elk(hass):
|
|||
assert result["type"] == "form"
|
||||
assert result["errors"] == {}
|
||||
|
||||
mocked_elk = mock_elk(invalid_auth=False)
|
||||
mocked_elk = mock_elk(invalid_auth=None, sync_complete=True)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.elkm1.config_flow.elkm1.Elk",
|
||||
|
@ -115,7 +125,7 @@ async def test_form_user_with_serial_elk(hass):
|
|||
assert result["type"] == "form"
|
||||
assert result["errors"] == {}
|
||||
|
||||
mocked_elk = mock_elk(invalid_auth=False)
|
||||
mocked_elk = mock_elk(invalid_auth=None, sync_complete=True)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.elkm1.config_flow.elkm1.Elk",
|
||||
|
@ -153,19 +163,21 @@ async def test_form_user_with_serial_elk(hass):
|
|||
|
||||
async def test_form_cannot_connect(hass):
|
||||
"""Test we handle cannot connect error."""
|
||||
from asyncio import TimeoutError
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
mocked_elk = mock_elk(invalid_auth=False)
|
||||
mocked_elk = mock_elk(invalid_auth=None, sync_complete=None)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.elkm1.config_flow.elkm1.Elk",
|
||||
return_value=mocked_elk,
|
||||
), patch(
|
||||
"homeassistant.components.elkm1.config_flow.async_wait_for_elk_to_sync",
|
||||
return_value=False,
|
||||
): # async_wait_for_elk_to_sync is being patched to avoid making the test wait 45s
|
||||
"homeassistant.components.elkm1.async_timeout.timeout",
|
||||
side_effect=TimeoutError,
|
||||
):
|
||||
result2 = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
|
@ -188,7 +200,7 @@ async def test_form_invalid_auth(hass):
|
|||
DOMAIN, context={"source": config_entries.SOURCE_USER}
|
||||
)
|
||||
|
||||
mocked_elk = mock_elk(invalid_auth=True)
|
||||
mocked_elk = mock_elk(invalid_auth=True, sync_complete=True)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.elkm1.config_flow.elkm1.Elk",
|
||||
|
@ -214,7 +226,7 @@ async def test_form_import(hass):
|
|||
"""Test we get the form with import source."""
|
||||
await setup.async_setup_component(hass, "persistent_notification", {})
|
||||
|
||||
mocked_elk = mock_elk(invalid_auth=False)
|
||||
mocked_elk = mock_elk(invalid_auth=False, sync_complete=True)
|
||||
with patch(
|
||||
"homeassistant.components.elkm1.config_flow.elkm1.Elk",
|
||||
return_value=mocked_elk,
|
||||
|
|
Loading…
Add table
Reference in a new issue