diff --git a/homeassistant/components/reolink/__init__.py b/homeassistant/components/reolink/__init__.py index bd521d74777..fee6567ab76 100644 --- a/homeassistant/components/reolink/__init__.py +++ b/homeassistant/components/reolink/__init__.py @@ -12,8 +12,10 @@ import async_timeout from reolink_aio.exceptions import ( ApiError, InvalidContentTypeError, + LoginError, NoDataError, ReolinkError, + UnexpectedDataError, ) from homeassistant.config_entries import ConfigEntry @@ -23,7 +25,7 @@ from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN -from .exceptions import UserNotAdmin +from .exceptions import ReolinkException, UserNotAdmin from .host import ReolinkHost _LOGGER = logging.getLogger(__name__) @@ -45,12 +47,7 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b host = ReolinkHost(hass, config_entry.data, config_entry.options) try: - if not await host.async_init(): - await host.stop() - raise ConfigEntryNotReady( - f"Error while trying to setup {host.api.host}:{host.api.port}: " - "failed to obtain data from device." - ) + await host.async_init() except UserNotAdmin as err: raise ConfigEntryAuthFailed(err) from UserNotAdmin except ( @@ -58,7 +55,10 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b asyncio.TimeoutError, ApiError, InvalidContentTypeError, + LoginError, NoDataError, + ReolinkException, + UnexpectedDataError, ) as err: await host.stop() raise ConfigEntryNotReady( diff --git a/homeassistant/components/reolink/config_flow.py b/homeassistant/components/reolink/config_flow.py index e8f1fe3abe9..faa9b28ac36 100644 --- a/homeassistant/components/reolink/config_flow.py +++ b/homeassistant/components/reolink/config_flow.py @@ -8,14 +8,14 @@ from typing import Any from reolink_aio.exceptions import ApiError, CredentialsInvalidError, ReolinkError import voluptuous as vol -from homeassistant import config_entries, exceptions +from homeassistant import config_entries from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME from homeassistant.core import callback from homeassistant.data_entry_flow import FlowResult from homeassistant.helpers import config_validation as cv from .const import CONF_PROTOCOL, CONF_USE_HTTPS, DEFAULT_PROTOCOL, DOMAIN -from .exceptions import UserNotAdmin +from .exceptions import ReolinkException, UserNotAdmin from .host import ReolinkHost _LOGGER = logging.getLogger(__name__) @@ -96,25 +96,25 @@ class ReolinkFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): if user_input is not None: host = ReolinkHost(self.hass, user_input, DEFAULT_OPTIONS) try: - await async_obtain_host_settings(host) + await host.async_init() except UserNotAdmin: errors[CONF_USERNAME] = "not_admin" placeholders["username"] = host.api.username placeholders["userlevel"] = host.api.user_level - except CannotConnect: - errors[CONF_HOST] = "cannot_connect" except CredentialsInvalidError: errors[CONF_HOST] = "invalid_auth" except ApiError as err: placeholders["error"] = str(err) errors[CONF_HOST] = "api_error" - except ReolinkError as err: + except (ReolinkError, ReolinkException) as err: placeholders["error"] = str(err) errors[CONF_HOST] = "cannot_connect" except Exception as err: # pylint: disable=broad-except _LOGGER.exception("Unexpected exception") placeholders["error"] = str(err) errors[CONF_HOST] = "unknown" + finally: + await host.stop() if not errors: user_input[CONF_PORT] = host.api.port @@ -160,16 +160,3 @@ class ReolinkFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): errors=errors, description_placeholders=placeholders, ) - - -async def async_obtain_host_settings(host: ReolinkHost) -> None: - """Initialize the Reolink host and get the host information.""" - try: - if not await host.async_init(): - raise CannotConnect - finally: - await host.stop() - - -class CannotConnect(exceptions.HomeAssistantError): - """Error to indicate we cannot connect.""" diff --git a/homeassistant/components/reolink/exceptions.py b/homeassistant/components/reolink/exceptions.py index ad95625cfa7..16fcffb064a 100644 --- a/homeassistant/components/reolink/exceptions.py +++ b/homeassistant/components/reolink/exceptions.py @@ -2,5 +2,13 @@ from homeassistant.exceptions import HomeAssistantError -class UserNotAdmin(HomeAssistantError): +class ReolinkException(HomeAssistantError): + """BaseException for the Reolink integration.""" + + +class ReolinkSetupException(ReolinkException): + """Raised when setting up the Reolink host failed.""" + + +class UserNotAdmin(ReolinkException): """Raised when user is not admin.""" diff --git a/homeassistant/components/reolink/host.py b/homeassistant/components/reolink/host.py index 6f4487d2001..8e7e435358f 100644 --- a/homeassistant/components/reolink/host.py +++ b/homeassistant/components/reolink/host.py @@ -8,18 +8,14 @@ from typing import Any import aiohttp from reolink_aio.api import Host -from reolink_aio.exceptions import ( - ApiError, - CredentialsInvalidError, - InvalidContentTypeError, -) +from reolink_aio.exceptions import ReolinkError from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import format_mac from .const import CONF_PROTOCOL, CONF_USE_HTTPS, DEFAULT_TIMEOUT -from .exceptions import UserNotAdmin +from .exceptions import ReolinkSetupException, UserNotAdmin _LOGGER = logging.getLogger(__name__) @@ -59,14 +55,14 @@ class ReolinkHost: """Return the API object.""" return self._api - async def async_init(self) -> bool: + async def async_init(self) -> None: """Connect to Reolink host.""" self._api.expire_session() await self._api.get_host_data() if self._api.mac_address is None: - return False + raise ReolinkSetupException("Could not get mac address") if not self._api.is_admin: await self.stop() @@ -96,11 +92,13 @@ class ReolinkHost: enable_rtsp = True if enable_onvif or enable_rtmp or enable_rtsp: - if not await self._api.set_net_port( - enable_onvif=enable_onvif, - enable_rtmp=enable_rtmp, - enable_rtsp=enable_rtsp, - ): + try: + await self._api.set_net_port( + enable_onvif=enable_onvif, + enable_rtmp=enable_rtmp, + enable_rtsp=enable_rtsp, + ) + except ReolinkError: if enable_onvif: _LOGGER.error( "Failed to enable ONVIF on %s. Set it to ON to receive notifications", @@ -120,8 +118,6 @@ class ReolinkHost: self._unique_id = format_mac(self._api.mac_address) - return True - async def update_states(self) -> None: """Call the API of the camera device to update the internal states.""" await self._api.get_states() @@ -145,22 +141,9 @@ class ReolinkHost: self._api.host, self._api.port, ) - except ApiError as err: + except ReolinkError as err: _LOGGER.error( - "Reolink API error while logging out for host %s:%s: %s", - self._api.host, - self._api.port, - str(err), - ) - except CredentialsInvalidError: - _LOGGER.error( - "Reolink credentials error while logging out for host %s:%s", - self._api.host, - self._api.port, - ) - except InvalidContentTypeError as err: - _LOGGER.error( - "Reolink content type error while logging out for host %s:%s: %s", + "Reolink error while logging out for host %s:%s: %s", self._api.host, self._api.port, str(err), diff --git a/homeassistant/components/reolink/manifest.json b/homeassistant/components/reolink/manifest.json index 92b0a0b9c1b..e0447363ce9 100644 --- a/homeassistant/components/reolink/manifest.json +++ b/homeassistant/components/reolink/manifest.json @@ -3,7 +3,7 @@ "name": "Reolink IP NVR/camera", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/reolink", - "requirements": ["reolink-aio==0.2.3"], + "requirements": ["reolink-aio==0.3.0"], "codeowners": ["@starkillerOG"], "iot_class": "local_polling", "loggers": ["reolink_aio"] diff --git a/requirements_all.txt b/requirements_all.txt index f848ab57fe2..e47acb71047 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2221,7 +2221,7 @@ regenmaschine==2022.11.0 renault-api==0.1.11 # homeassistant.components.reolink -reolink-aio==0.2.3 +reolink-aio==0.3.0 # homeassistant.components.python_script restrictedpython==6.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e97218f1c2d..b6579a4c3e6 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1566,7 +1566,7 @@ regenmaschine==2022.11.0 renault-api==0.1.11 # homeassistant.components.reolink -reolink-aio==0.2.3 +reolink-aio==0.3.0 # homeassistant.components.python_script restrictedpython==6.0