diff --git a/homeassistant/components/vicare/binary_sensor.py b/homeassistant/components/vicare/binary_sensor.py index 1fd023265d7d..c5c1f6fbf944 100644 --- a/homeassistant/components/vicare/binary_sensor.py +++ b/homeassistant/components/vicare/binary_sensor.py @@ -12,14 +12,7 @@ from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig from PyViCare.PyViCareHeatingDevice import ( HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent, ) -from PyViCare.PyViCareUtils import ( - PyViCareDeviceCommunicationError, - PyViCareInternalServerError, - PyViCareInvalidDataError, - PyViCareNotSupportedFeatureError, - PyViCareRateLimitError, -) -import requests +from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, @@ -233,18 +226,5 @@ class ViCareBinarySensor(ViCareEntity, BinarySensorEntity): def update(self) -> None: """Update state of sensor.""" - try: - with suppress(PyViCareNotSupportedFeatureError): - self._attr_is_on = self.entity_description.value_getter(self._api) - except requests.exceptions.ConnectionError: - _LOGGER.error("Unable to retrieve data from ViCare server") - except ValueError: - _LOGGER.error("Unable to decode data from ViCare server") - except PyViCareRateLimitError as limit_exception: - _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception) - except PyViCareInvalidDataError as invalid_data_exception: - _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception) - except PyViCareDeviceCommunicationError as comm_exception: - _LOGGER.warning("Device communication error: %s", comm_exception) - except PyViCareInternalServerError as server_exception: - _LOGGER.warning("Vicare server error: %s", server_exception) + with self.vicare_api_handler(), suppress(PyViCareNotSupportedFeatureError): + self._attr_is_on = self.entity_description.value_getter(self._api) diff --git a/homeassistant/components/vicare/button.py b/homeassistant/components/vicare/button.py index 8207695b4361..852cf2a9062e 100644 --- a/homeassistant/components/vicare/button.py +++ b/homeassistant/components/vicare/button.py @@ -8,14 +8,7 @@ import logging from PyViCare.PyViCareDevice import Device as PyViCareDevice from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig -from PyViCare.PyViCareUtils import ( - PyViCareDeviceCommunicationError, - PyViCareInternalServerError, - PyViCareInvalidDataError, - PyViCareNotSupportedFeatureError, - PyViCareRateLimitError, -) -import requests +from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError from homeassistant.components.button import ButtonEntity, ButtonEntityDescription from homeassistant.const import EntityCategory @@ -104,18 +97,5 @@ class ViCareButton(ViCareEntity, ButtonEntity): def press(self) -> None: """Handle the button press.""" - try: - with suppress(PyViCareNotSupportedFeatureError): - self.entity_description.value_setter(self._api) - except requests.exceptions.ConnectionError: - _LOGGER.error("Unable to retrieve data from ViCare server") - except ValueError: - _LOGGER.error("Unable to decode data from ViCare server") - except PyViCareRateLimitError as limit_exception: - _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception) - except PyViCareInvalidDataError as invalid_data_exception: - _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception) - except PyViCareDeviceCommunicationError as comm_exception: - _LOGGER.warning("Device communication error: %s", comm_exception) - except PyViCareInternalServerError as server_exception: - _LOGGER.warning("Vicare server error: %s", server_exception) + with self.vicare_api_handler(), suppress(PyViCareNotSupportedFeatureError): + self.entity_description.value_setter(self._api) diff --git a/homeassistant/components/vicare/climate.py b/homeassistant/components/vicare/climate.py index cacc3d7fc153..9f23c60085e5 100644 --- a/homeassistant/components/vicare/climate.py +++ b/homeassistant/components/vicare/climate.py @@ -11,13 +11,8 @@ from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig from PyViCare.PyViCareHeatingDevice import HeatingCircuit as PyViCareHeatingCircuit from PyViCare.PyViCareUtils import ( PyViCareCommandError, - PyViCareDeviceCommunicationError, - PyViCareInternalServerError, - PyViCareInvalidDataError, PyViCareNotSupportedFeatureError, - PyViCareRateLimitError, ) -import requests import voluptuous as vol from homeassistant.components.climate import ( @@ -160,7 +155,7 @@ class ViCareClimate(ViCareEntity, ClimateEntity): def update(self) -> None: """Let HA know there has been an update from the ViCare API.""" - try: + with self.vicare_api_handler(): _room_temperature = None with suppress(PyViCareNotSupportedFeatureError): self._attributes["room_temperature"] = _room_temperature = ( @@ -216,19 +211,6 @@ class ViCareClimate(ViCareEntity, ClimateEntity): self._current_action or compressor.getActive() ) - except requests.exceptions.ConnectionError: - _LOGGER.error("Unable to retrieve data from ViCare server") - except PyViCareRateLimitError as limit_exception: - _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception) - except ValueError: - _LOGGER.error("Unable to decode data from ViCare server") - except PyViCareInvalidDataError as invalid_data_exception: - _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception) - except PyViCareDeviceCommunicationError as comm_exception: - _LOGGER.warning("Device communication error: %s", comm_exception) - except PyViCareInternalServerError as server_exception: - _LOGGER.warning("Vicare server error: %s", server_exception) - @property def hvac_mode(self) -> HVACMode | None: """Return current hvac mode.""" diff --git a/homeassistant/components/vicare/entity.py b/homeassistant/components/vicare/entity.py index bcfda71cdfda..4502e12ff864 100644 --- a/homeassistant/components/vicare/entity.py +++ b/homeassistant/components/vicare/entity.py @@ -1,22 +1,53 @@ """Entities for the ViCare integration.""" +from collections.abc import Generator +from contextlib import contextmanager +import logging + from PyViCare.PyViCareDevice import Device as PyViCareDevice from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig from PyViCare.PyViCareHeatingDevice import ( HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent, ) +from PyViCare.PyViCareUtils import ( + PyViCareDeviceCommunicationError, + PyViCareInternalServerError, + PyViCareInvalidDataError, + PyViCareRateLimitError, +) +from requests.exceptions import ConnectionError as RequestConnectionError from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity import Entity from .const import DOMAIN, VIESSMANN_DEVELOPER_PORTAL +_LOGGER = logging.getLogger(__name__) + class ViCareEntity(Entity): """Base class for ViCare entities.""" _attr_has_entity_name = True + @contextmanager + def vicare_api_handler(self) -> Generator[None]: + """Handle common ViCare API errors.""" + try: + yield + except RequestConnectionError: + _LOGGER.error("Unable to retrieve data from ViCare server") + except ValueError: + _LOGGER.error("Unable to decode data from ViCare server") + except PyViCareRateLimitError as err: + _LOGGER.error("ViCare API rate limit exceeded: %s", err) + except PyViCareInvalidDataError as err: + _LOGGER.error("Invalid data from ViCare server: %s", err) + except PyViCareDeviceCommunicationError as err: + _LOGGER.warning("Device communication error: %s", err) + except PyViCareInternalServerError as err: + _LOGGER.warning("ViCare server error: %s", err) + def __init__( self, unique_id_suffix: str, diff --git a/homeassistant/components/vicare/fan.py b/homeassistant/components/vicare/fan.py index a5bffe0986e1..87fca8d6cf61 100644 --- a/homeassistant/components/vicare/fan.py +++ b/homeassistant/components/vicare/fan.py @@ -9,14 +9,7 @@ from typing import Any from PyViCare.PyViCareDevice import Device as PyViCareDevice from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig -from PyViCare.PyViCareUtils import ( - PyViCareDeviceCommunicationError, - PyViCareInternalServerError, - PyViCareInvalidDataError, - PyViCareNotSupportedFeatureError, - PyViCareRateLimitError, -) -from requests.exceptions import ConnectionError as RequestConnectionError +from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError from homeassistant.components.fan import FanEntity, FanEntityFeature from homeassistant.core import HomeAssistant @@ -173,7 +166,7 @@ class ViCareFan(ViCareEntity, FanEntity): def update(self) -> None: """Update state of fan.""" level: str | None = None - try: + with self.vicare_api_handler(): with suppress(PyViCareNotSupportedFeatureError): self._attr_preset_mode = VentilationMode.from_vicare_mode( self._api.getActiveVentilationMode() @@ -187,18 +180,6 @@ class ViCareFan(ViCareEntity, FanEntity): ) else: self._attr_percentage = 0 - except RequestConnectionError: - _LOGGER.error("Unable to retrieve data from ViCare server") - except ValueError: - _LOGGER.error("Unable to decode data from ViCare server") - except PyViCareRateLimitError as limit_exception: - _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception) - except PyViCareInvalidDataError as invalid_data_exception: - _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception) - except PyViCareDeviceCommunicationError as comm_exception: - _LOGGER.warning("Device communication error: %s", comm_exception) - except PyViCareInternalServerError as server_exception: - _LOGGER.warning("Vicare server error: %s", server_exception) @property def is_on(self) -> bool | None: diff --git a/homeassistant/components/vicare/number.py b/homeassistant/components/vicare/number.py index 9f92be602175..de43b5a17974 100644 --- a/homeassistant/components/vicare/number.py +++ b/homeassistant/components/vicare/number.py @@ -13,14 +13,7 @@ from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig from PyViCare.PyViCareHeatingDevice import ( HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent, ) -from PyViCare.PyViCareUtils import ( - PyViCareDeviceCommunicationError, - PyViCareInternalServerError, - PyViCareInvalidDataError, - PyViCareNotSupportedFeatureError, - PyViCareRateLimitError, -) -from requests.exceptions import ConnectionError as RequestConnectionError +from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError from homeassistant.components.number import ( NumberDeviceClass, @@ -437,38 +430,23 @@ class ViCareNumber(ViCareEntity, NumberEntity): def update(self) -> None: """Update state of number.""" - try: - with suppress(PyViCareNotSupportedFeatureError): - self._attr_native_value = self.entity_description.value_getter( - self._api - ) + with self.vicare_api_handler(), suppress(PyViCareNotSupportedFeatureError): + self._attr_native_value = self.entity_description.value_getter(self._api) - if min_value := _get_value( - self.entity_description.min_value_getter, self._api - ): - self._attr_native_min_value = min_value + if min_value := _get_value( + self.entity_description.min_value_getter, self._api + ): + self._attr_native_min_value = min_value - if max_value := _get_value( - self.entity_description.max_value_getter, self._api - ): - self._attr_native_max_value = max_value + if max_value := _get_value( + self.entity_description.max_value_getter, self._api + ): + self._attr_native_max_value = max_value - if stepping_value := _get_value( - self.entity_description.stepping_getter, self._api - ): - self._attr_native_step = stepping_value - except RequestConnectionError: - _LOGGER.error("Unable to retrieve data from ViCare server") - except ValueError: - _LOGGER.error("Unable to decode data from ViCare server") - except PyViCareRateLimitError as limit_exception: - _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception) - except PyViCareInvalidDataError as invalid_data_exception: - _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception) - except PyViCareDeviceCommunicationError as comm_exception: - _LOGGER.warning("Device communication error: %s", comm_exception) - except PyViCareInternalServerError as server_exception: - _LOGGER.warning("Vicare server error: %s", server_exception) + if stepping_value := _get_value( + self.entity_description.stepping_getter, self._api + ): + self._attr_native_step = stepping_value def _get_value( diff --git a/homeassistant/components/vicare/sensor.py b/homeassistant/components/vicare/sensor.py index 7b8ec1bd285c..1cc02eb305d7 100644 --- a/homeassistant/components/vicare/sensor.py +++ b/homeassistant/components/vicare/sensor.py @@ -12,14 +12,7 @@ from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig from PyViCare.PyViCareHeatingDevice import ( HeatingDeviceWithComponent as PyViCareHeatingDeviceComponent, ) -from PyViCare.PyViCareUtils import ( - PyViCareDeviceCommunicationError, - PyViCareInternalServerError, - PyViCareInvalidDataError, - PyViCareNotSupportedFeatureError, - PyViCareRateLimitError, -) -import requests +from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError from homeassistant.components.sensor import ( SensorDeviceClass, @@ -1556,26 +1549,11 @@ class ViCareSensor(ViCareEntity, SensorEntity): def update(self) -> None: """Update state of sensor.""" vicare_unit = None - try: - with suppress(PyViCareNotSupportedFeatureError): - self._attr_native_value = self.entity_description.value_getter( - self._api - ) + with self.vicare_api_handler(), suppress(PyViCareNotSupportedFeatureError): + self._attr_native_value = self.entity_description.value_getter(self._api) - if self.entity_description.unit_getter: - vicare_unit = self.entity_description.unit_getter(self._api) - except requests.exceptions.ConnectionError: - _LOGGER.error("Unable to retrieve data from ViCare server") - except ValueError: - _LOGGER.error("Unable to decode data from ViCare server") - except PyViCareRateLimitError as limit_exception: - _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception) - except PyViCareInvalidDataError as invalid_data_exception: - _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception) - except PyViCareDeviceCommunicationError as comm_exception: - _LOGGER.warning("Device communication error: %s", comm_exception) - except PyViCareInternalServerError as server_exception: - _LOGGER.warning("Vicare server error: %s", server_exception) + if self.entity_description.unit_getter: + vicare_unit = self.entity_description.unit_getter(self._api) if vicare_unit is not None: if ( diff --git a/homeassistant/components/vicare/water_heater.py b/homeassistant/components/vicare/water_heater.py index ab1b2bfd9613..7693f63b3ae2 100644 --- a/homeassistant/components/vicare/water_heater.py +++ b/homeassistant/components/vicare/water_heater.py @@ -9,14 +9,7 @@ from typing import Any from PyViCare.PyViCareDevice import Device as PyViCareDevice from PyViCare.PyViCareDeviceConfig import PyViCareDeviceConfig from PyViCare.PyViCareHeatingDevice import HeatingCircuit as PyViCareHeatingCircuit -from PyViCare.PyViCareUtils import ( - PyViCareDeviceCommunicationError, - PyViCareInternalServerError, - PyViCareInvalidDataError, - PyViCareNotSupportedFeatureError, - PyViCareRateLimitError, -) -import requests +from PyViCare.PyViCareUtils import PyViCareNotSupportedFeatureError from homeassistant.components.water_heater import ( WaterHeaterEntity, @@ -120,7 +113,7 @@ class ViCareWater(ViCareEntity, WaterHeaterEntity): def update(self) -> None: """Let HA know there has been an update from the ViCare API.""" - try: + with self.vicare_api_handler(): with suppress(PyViCareNotSupportedFeatureError): self._attr_current_temperature = ( self._api.getDomesticHotWaterStorageTemperature() @@ -137,19 +130,6 @@ class ViCareWater(ViCareEntity, WaterHeaterEntity): with suppress(PyViCareNotSupportedFeatureError): self._dhw_active = self._api.getDomesticHotWaterActive() - except requests.exceptions.ConnectionError: - _LOGGER.error("Unable to retrieve data from ViCare server") - except PyViCareRateLimitError as limit_exception: - _LOGGER.error("Vicare API rate limit exceeded: %s", limit_exception) - except ValueError: - _LOGGER.error("Unable to decode data from ViCare server") - except PyViCareInvalidDataError as invalid_data_exception: - _LOGGER.error("Invalid data from Vicare server: %s", invalid_data_exception) - except PyViCareDeviceCommunicationError as comm_exception: - _LOGGER.warning("Device communication error: %s", comm_exception) - except PyViCareInternalServerError as server_exception: - _LOGGER.warning("Vicare server error: %s", server_exception) - def set_temperature(self, **kwargs: Any) -> None: """Set new target temperatures.""" if (temp := kwargs.get(ATTR_TEMPERATURE)) is not None: