mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 05:07:41 +00:00
Streamline exception handling in Guardian (#107053)
This commit is contained in:
parent
fce869248c
commit
50fbcaf20f
@ -2,9 +2,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Awaitable, Callable, Coroutine
|
from collections.abc import Callable, Coroutine
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, cast
|
from typing import Any
|
||||||
|
|
||||||
from aioguardian import Client
|
from aioguardian import Client
|
||||||
from aioguardian.errors import GuardianError
|
from aioguardian.errors import GuardianError
|
||||||
@ -302,9 +302,7 @@ class PairedSensorManager:
|
|||||||
entry=self._entry,
|
entry=self._entry,
|
||||||
client=self._client,
|
client=self._client,
|
||||||
api_name=f"{API_SENSOR_PAIRED_SENSOR_STATUS}_{uid}",
|
api_name=f"{API_SENSOR_PAIRED_SENSOR_STATUS}_{uid}",
|
||||||
api_coro=lambda: cast(
|
api_coro=lambda: self._client.sensor.paired_sensor_status(uid),
|
||||||
Awaitable, self._client.sensor.paired_sensor_status(uid)
|
|
||||||
),
|
|
||||||
api_lock=self._api_lock,
|
api_lock=self._api_lock,
|
||||||
valve_controller_uid=self._entry.data[CONF_UID],
|
valve_controller_uid=self._entry.data[CONF_UID],
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,6 @@ from collections.abc import Awaitable, Callable
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from aioguardian import Client
|
from aioguardian import Client
|
||||||
from aioguardian.errors import GuardianError
|
|
||||||
|
|
||||||
from homeassistant.components.button import (
|
from homeassistant.components.button import (
|
||||||
ButtonDeviceClass,
|
ButtonDeviceClass,
|
||||||
@ -15,12 +14,12 @@ from homeassistant.components.button import (
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import EntityCategory
|
from homeassistant.const import EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import GuardianData, ValveControllerEntity, ValveControllerEntityDescription
|
from . import GuardianData, ValveControllerEntity, ValveControllerEntityDescription
|
||||||
from .const import API_SYSTEM_DIAGNOSTICS, DOMAIN
|
from .const import API_SYSTEM_DIAGNOSTICS, DOMAIN
|
||||||
|
from .util import convert_exceptions_to_homeassistant_error
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True, kw_only=True)
|
@dataclass(frozen=True, kw_only=True)
|
||||||
@ -96,14 +95,10 @@ class GuardianButton(ValveControllerEntity, ButtonEntity):
|
|||||||
|
|
||||||
self._client = data.client
|
self._client = data.client
|
||||||
|
|
||||||
|
@convert_exceptions_to_homeassistant_error
|
||||||
async def async_press(self) -> None:
|
async def async_press(self) -> None:
|
||||||
"""Send out a restart command."""
|
"""Send out a restart command."""
|
||||||
try:
|
async with self._client:
|
||||||
async with self._client:
|
await self.entity_description.push_action(self._client)
|
||||||
await self.entity_description.push_action(self._client)
|
|
||||||
except GuardianError as err:
|
|
||||||
raise HomeAssistantError(
|
|
||||||
f'Error while pressing button "{self.entity_id}": {err}'
|
|
||||||
) from err
|
|
||||||
|
|
||||||
async_dispatcher_send(self.hass, self.coordinator.signal_reboot_requested)
|
async_dispatcher_send(self.hass, self.coordinator.signal_reboot_requested)
|
||||||
|
@ -6,17 +6,16 @@ from dataclasses import dataclass
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from aioguardian import Client
|
from aioguardian import Client
|
||||||
from aioguardian.errors import GuardianError
|
|
||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import EntityCategory
|
from homeassistant.const import EntityCategory
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import GuardianData, ValveControllerEntity, ValveControllerEntityDescription
|
from . import GuardianData, ValveControllerEntity, ValveControllerEntityDescription
|
||||||
from .const import API_VALVE_STATUS, API_WIFI_STATUS, DOMAIN
|
from .const import API_VALVE_STATUS, API_WIFI_STATUS, DOMAIN
|
||||||
|
from .util import convert_exceptions_to_homeassistant_error
|
||||||
|
|
||||||
ATTR_AVG_CURRENT = "average_current"
|
ATTR_AVG_CURRENT = "average_current"
|
||||||
ATTR_CONNECTED_CLIENTS = "connected_clients"
|
ATTR_CONNECTED_CLIENTS = "connected_clients"
|
||||||
@ -139,34 +138,16 @@ class ValveControllerSwitch(ValveControllerEntity, SwitchEntity):
|
|||||||
"""Return True if entity is on."""
|
"""Return True if entity is on."""
|
||||||
return self.entity_description.is_on_fn(self.coordinator.data)
|
return self.entity_description.is_on_fn(self.coordinator.data)
|
||||||
|
|
||||||
|
@convert_exceptions_to_homeassistant_error
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
"""Turn the switch off."""
|
"""Turn the switch off."""
|
||||||
if not self._attr_is_on:
|
async with self._client:
|
||||||
return
|
await self.entity_description.off_fn(self._client)
|
||||||
|
await self.coordinator.async_request_refresh()
|
||||||
try:
|
|
||||||
async with self._client:
|
|
||||||
await self.entity_description.off_fn(self._client)
|
|
||||||
except GuardianError as err:
|
|
||||||
raise HomeAssistantError(
|
|
||||||
f'Error while turning "{self.entity_id}" off: {err}'
|
|
||||||
) from err
|
|
||||||
|
|
||||||
self._attr_is_on = False
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
|
@convert_exceptions_to_homeassistant_error
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the switch on."""
|
"""Turn the switch on."""
|
||||||
if self._attr_is_on:
|
async with self._client:
|
||||||
return
|
await self.entity_description.on_fn(self._client)
|
||||||
|
await self.coordinator.async_request_refresh()
|
||||||
try:
|
|
||||||
async with self._client:
|
|
||||||
await self.entity_description.on_fn(self._client)
|
|
||||||
except GuardianError as err:
|
|
||||||
raise HomeAssistantError(
|
|
||||||
f'Error while turning "{self.entity_id}" on: {err}'
|
|
||||||
) from err
|
|
||||||
|
|
||||||
self._attr_is_on = True
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
@ -2,22 +2,29 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Awaitable, Callable, Iterable
|
from collections.abc import Callable, Coroutine, Iterable
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from typing import Any, cast
|
from functools import wraps
|
||||||
|
from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar, cast
|
||||||
|
|
||||||
from aioguardian import Client
|
from aioguardian import Client
|
||||||
from aioguardian.errors import GuardianError
|
from aioguardian.errors import GuardianError
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import LOGGER
|
from .const import LOGGER
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from . import GuardianEntity
|
||||||
|
|
||||||
|
_GuardianEntityT = TypeVar("_GuardianEntityT", bound=GuardianEntity)
|
||||||
|
|
||||||
DEFAULT_UPDATE_INTERVAL = timedelta(seconds=30)
|
DEFAULT_UPDATE_INTERVAL = timedelta(seconds=30)
|
||||||
|
|
||||||
SIGNAL_REBOOT_REQUESTED = "guardian_reboot_requested_{0}"
|
SIGNAL_REBOOT_REQUESTED = "guardian_reboot_requested_{0}"
|
||||||
@ -68,7 +75,7 @@ class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]):
|
|||||||
entry: ConfigEntry,
|
entry: ConfigEntry,
|
||||||
client: Client,
|
client: Client,
|
||||||
api_name: str,
|
api_name: str,
|
||||||
api_coro: Callable[..., Awaitable],
|
api_coro: Callable[..., Coroutine[Any, Any, dict[str, Any]]],
|
||||||
api_lock: asyncio.Lock,
|
api_lock: asyncio.Lock,
|
||||||
valve_controller_uid: str,
|
valve_controller_uid: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -112,3 +119,27 @@ class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]):
|
|||||||
self.hass, self.signal_reboot_requested, async_reboot_requested
|
self.hass, self.signal_reboot_requested, async_reboot_requested
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_P = ParamSpec("_P")
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def convert_exceptions_to_homeassistant_error(
|
||||||
|
func: Callable[Concatenate[_GuardianEntityT, _P], Coroutine[Any, Any, Any]],
|
||||||
|
) -> Callable[Concatenate[_GuardianEntityT, _P], Coroutine[Any, Any, None]]:
|
||||||
|
"""Decorate to handle exceptions from the Guardian API."""
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
async def wrapper(
|
||||||
|
entity: _GuardianEntityT, *args: _P.args, **kwargs: _P.kwargs
|
||||||
|
) -> None:
|
||||||
|
"""Wrap the provided function."""
|
||||||
|
try:
|
||||||
|
await func(entity, *args, **kwargs)
|
||||||
|
except GuardianError as err:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Error while calling {func.__name__}: {err}"
|
||||||
|
) from err
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
Loading…
x
Reference in New Issue
Block a user