Skip to content

Commit

Permalink
Merge pull request #308 from petretiandrea/refactor/better-exception-…
Browse files Browse the repository at this point in the history
…handling

refactor: handling tapo exception
  • Loading branch information
petretiandrea authored Dec 31, 2022
2 parents 800f64f + 4678506 commit 86ed991
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 28 deletions.
26 changes: 21 additions & 5 deletions custom_components/tapo/common_setup.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
from typing import Dict, Any
from datetime import timedelta
import logging
import aiohttp
import async_timeout
from plugp100 import TapoApiClient, TapoApiClientConfig, TapoDeviceState
from plugp100 import (
TapoApiClient,
TapoApiClientConfig,
TapoDeviceState,
TapoException,
TapoError,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.helpers.update_coordinator import UpdateFailed
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.exceptions import ConfigEntryNotReady, ConfigEntryAuthFailed
from homeassistant.helpers.debounce import Debouncer
from custom_components.tapo.const import (
DOMAIN,
Expand Down Expand Up @@ -97,10 +104,12 @@ async def _async_update_data(self):
try:
async with async_timeout.timeout(10):
return await self._update_with_fallback()
except TapoException as error:
self._raise_from_tapo_exception(error)
except (aiohttp.ClientError) as error:
raise UpdateFailed(f"Error communication with API: {error}") from error
except Exception as exception:
raise UpdateFailed(
f"Error communication with API: {exception}"
) from exception
raise UpdateFailed(f"Unexpected exception: {exception}") from exception

async def _update_with_fallback(self, retry=True):
try:
Expand All @@ -109,3 +118,10 @@ async def _update_with_fallback(self, retry=True):
if retry:
await self.api.login()
return await self._update_with_fallback(False)

def _raise_from_tapo_exception(self, exception: TapoException):
_LOGGGER.error("Tapo exception: %s", str(exception))
if exception.error_code == TapoError.INVALID_CREDENTIAL.value:
raise ConfigEntryAuthFailed from exception
else:
raise UpdateFailed(f"Error tapo exception: {exception}") from exception
32 changes: 22 additions & 10 deletions custom_components/tapo/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
"""Config flow for tapo integration."""
import logging
from typing import Any
import aiohttp

import voluptuous as vol

from homeassistant import config_entries, exceptions
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from homeassistant import data_entry_flow
from plugp100 import TapoApiClient, TapoApiClientConfig
from plugp100 import TapoApiClient, TapoApiClientConfig, TapoException, TapoError

from custom_components.tapo.const import (
DOMAIN,
CONF_HOST,
CONF_USERNAME,
CONF_PASSWORD,
) # pylint:disable=unused-import
)


_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -61,15 +62,15 @@ async def async_step_user(
await self.async_set_unique_id(unique_id)
self._abort_if_unique_id_configured()
self.hass.data[DOMAIN][f"{unique_id}_api"] = api
except CannotConnect as error:
errors["base"] = "cannot_connect"
_LOGGER.error("Failed to setup %s", str(error))
except InvalidAuth as error:
errors["base"] = "invalid_auth"
_LOGGER.error("Failed to setup %s", str(error))
_LOGGER.error("Failed to setup, invalid auth %s", str(error))
except CannotConnect as error:
errors["base"] = "cannot_connect"
_LOGGER.error("Failed to setup cannot connect %s", str(error))
except InvalidHost as error:
errors["base"] = "invalid_hostname"
_LOGGER.error("Failed to setup %s", str(error))
_LOGGER.error("Failed to setup invalid host %s", str(error))
except data_entry_flow.AbortFlow:
return self.async_abort(reason="already_configured")
except Exception as error: # pylint: disable=broad-except
Expand All @@ -86,7 +87,9 @@ async def _get_unique_data_from_api(self, api: TapoApiClient) -> dict[str, Any]:
try:
state = await api.get_state()
return {"title": state.nickname, "unique_id": state.device_id}
except Exception as error:
except TapoException as error:
self._raise_from_tapo_exception(error)
except (aiohttp.ClientError, Exception) as error:
raise CannotConnect from error

async def _try_setup_api(
Expand All @@ -103,8 +106,17 @@ async def _try_setup_api(
client = TapoApiClient.from_config(config)
await client.login()
return client
except Exception as error:
raise InvalidAuth from error
except TapoException as error:
self._raise_from_tapo_exception(error)
except (aiohttp.ClientError, Exception) as error:
raise CannotConnect from error

def _raise_from_tapo_exception(self, exception: TapoException):
_LOGGER.error("Tapo exception %s", str(exception.error_code))
if exception.error_code == TapoError.INVALID_CREDENTIAL.value:
raise InvalidAuth from exception
else:
raise CannotConnect from exception


class CannotConnect(exceptions.HomeAssistantError):
Expand Down
2 changes: 1 addition & 1 deletion custom_components/tapo/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"documentation": "https://github.com/petretiandrea/home-assistant-tapo-p100",
"issue_tracker": "https://github.com/petretiandrea/home-assistant-tapo-p100/issues/",
"requirements": [
"plugp100==2.1.21"
"plugp100==2.2.1"
],
"dependencies": [],
"codeowners": [
Expand Down
12 changes: 8 additions & 4 deletions custom_components/tapo/tapo_entity.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
from typing import Callable, Awaitable, TypeVar
from homeassistant.core import callback
from homeassistant.helpers.entity import DeviceInfo
Expand All @@ -6,11 +7,13 @@
from custom_components.tapo.common_setup import TapoCoordinator
from custom_components.tapo.const import DOMAIN

_LOGGER = logging.getLogger(__name__)


class TapoEntity(CoordinatorEntity):
def __init__(self, coordiantor: TapoCoordinator):
super().__init__(coordiantor)
self._data = coordiantor.data
def __init__(self, coordinator: TapoCoordinator):
super().__init__(coordinator)
self._data = coordinator.data

@property
def _tapo_coordinator(self) -> TapoCoordinator:
Expand Down Expand Up @@ -51,7 +54,8 @@ async def _execute_with_fallback(
) -> T:
try:
return await function()
except Exception:
except Exception as error: # pylint: disable=broad-except
_LOGGER.error("Error during command execution %s", str(error))
if retry:
await self.coordinator.api.login()
return await self._execute_with_fallback(function, False)
4 changes: 2 additions & 2 deletions custom_components/tapo/translations/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"error": {
"cannot_connect": "فشل في الاتصال",
"invalid_auth": "مصادقة غير صالحة",
"invalid_auth": "بيانات الاعتماد غير صالحة",
"unknown": "خطأ غير متوقع"
},
"step": {
Expand All @@ -19,4 +19,4 @@
}
},
"title": "tapo_p100"
}
}
4 changes: 2 additions & 2 deletions custom_components/tapo/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"error": {
"cannot_connect": "Failed to connect",
"invalid_auth": "Invalid authentication",
"invalid_auth": "Invalid credentials",
"unknown": "Unexpected error"
},
"step": {
Expand All @@ -19,4 +19,4 @@
}
},
"title": "tapo_p100"
}
}
4 changes: 2 additions & 2 deletions custom_components/tapo/translations/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"error": {
"cannot_connect": "Falhou ao conectar",
"invalid_auth": "Autenticação inválida",
"invalid_auth": "Credenciais inválidas",
"unknown": "Erro inesperado"
},
"step": {
Expand All @@ -19,4 +19,4 @@
}
},
"title": "tapo_p100"
}
}
1 change: 0 additions & 1 deletion custom_components/tapo/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@

def clamp(value, min_value, max_value):
return max(min(value, max_value), min_value)
2 changes: 1 addition & 1 deletion requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
homeassistant
plugp100==2.1.21
plugp100==2.2.1

0 comments on commit 86ed991

Please sign in to comment.