From 3d2ff841d338421ce79d2f38aa41eaaeb7a303cb Mon Sep 17 00:00:00 2001 From: Hans Oischinger Date: Wed, 6 Nov 2019 22:46:18 +0100 Subject: [PATCH] Handle exceptions from PyViCare library (#28536) * ViCare: Handle exceptions from PyViCare library (#28072) Sometimes Viessmann server failures or other connection problems may lead to exceptions thrown when updating data. This commit handles those exceptions with some error logging and makes sure that the component does not break completely in that case. * Remove unneeded returns * Remove unneeded returns --- homeassistant/components/vicare/climate.py | 93 +++++++++++-------- .../components/vicare/water_heater.py | 25 +++-- 2 files changed, 70 insertions(+), 48 deletions(-) diff --git a/homeassistant/components/vicare/climate.py b/homeassistant/components/vicare/climate.py index fe162c0c837..7e330383b30 100644 --- a/homeassistant/components/vicare/climate.py +++ b/homeassistant/components/vicare/climate.py @@ -1,5 +1,7 @@ """Viessmann ViCare climate device.""" import logging +import requests +import simplejson from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( @@ -111,55 +113,64 @@ class ViCareClimate(ClimateDevice): def update(self): """Let HA know there has been an update from the ViCare API.""" - _room_temperature = self._api.getRoomTemperature() - _supply_temperature = self._api.getSupplyTemperature() - if _room_temperature is not None and _room_temperature != PYVICARE_ERROR: - self._current_temperature = _room_temperature - elif _supply_temperature != PYVICARE_ERROR: - self._current_temperature = _supply_temperature - else: - self._current_temperature = None - self._current_program = self._api.getActiveProgram() + try: + _room_temperature = self._api.getRoomTemperature() + _supply_temperature = self._api.getSupplyTemperature() + if _room_temperature is not None and _room_temperature != PYVICARE_ERROR: + self._current_temperature = _room_temperature + elif _supply_temperature != PYVICARE_ERROR: + self._current_temperature = _supply_temperature + else: + self._current_temperature = None + self._current_program = self._api.getActiveProgram() - # The getCurrentDesiredTemperature call can yield 'error' (str) when the system is in standby - desired_temperature = self._api.getCurrentDesiredTemperature() - if desired_temperature == PYVICARE_ERROR: - desired_temperature = None + # The getCurrentDesiredTemperature call can yield 'error' (str) when the system is in standby + desired_temperature = self._api.getCurrentDesiredTemperature() + if desired_temperature == PYVICARE_ERROR: + desired_temperature = None - self._target_temperature = desired_temperature + self._target_temperature = desired_temperature - self._current_mode = self._api.getActiveMode() + self._current_mode = self._api.getActiveMode() - # Update the generic device attributes - self._attributes = {} - self._attributes["room_temperature"] = _room_temperature - self._attributes["supply_temperature"] = _supply_temperature - self._attributes["outside_temperature"] = self._api.getOutsideTemperature() - self._attributes["active_vicare_program"] = self._current_program - self._attributes["active_vicare_mode"] = self._current_mode - self._attributes["heating_curve_slope"] = self._api.getHeatingCurveSlope() - self._attributes["heating_curve_shift"] = self._api.getHeatingCurveShift() - self._attributes[ - "month_since_last_service" - ] = self._api.getMonthSinceLastService() - self._attributes["date_last_service"] = self._api.getLastServiceDate() - self._attributes["error_history"] = self._api.getErrorHistory() - self._attributes["active_error"] = self._api.getActiveError() - self._attributes[ - "circulationpump_active" - ] = self._api.getCirculationPumpActive() + # Update the generic device attributes + self._attributes = {} + self._attributes["room_temperature"] = _room_temperature + self._attributes["supply_temperature"] = _supply_temperature + self._attributes["outside_temperature"] = self._api.getOutsideTemperature() + self._attributes["active_vicare_program"] = self._current_program + self._attributes["active_vicare_mode"] = self._current_mode + self._attributes["heating_curve_slope"] = self._api.getHeatingCurveSlope() + self._attributes["heating_curve_shift"] = self._api.getHeatingCurveShift() + self._attributes[ + "month_since_last_service" + ] = self._api.getMonthSinceLastService() + self._attributes["date_last_service"] = self._api.getLastServiceDate() + self._attributes["error_history"] = self._api.getErrorHistory() + self._attributes["active_error"] = self._api.getActiveError() + self._attributes[ + "circulationpump_active" + ] = self._api.getCirculationPumpActive() - # Update the specific device attributes - if self._heating_type == HeatingType.gas: - self._current_action = self._api.getBurnerActive() + # Update the specific device attributes + if self._heating_type == HeatingType.gas: + self._current_action = self._api.getBurnerActive() - self._attributes["burner_modulation"] = self._api.getBurnerModulation() - self._attributes["boiler_temperature"] = self._api.getBoilerTemperature() + self._attributes["burner_modulation"] = self._api.getBurnerModulation() + self._attributes[ + "boiler_temperature" + ] = self._api.getBoilerTemperature() - elif self._heating_type == HeatingType.heatpump: - self._current_action = self._api.getCompressorActive() + elif self._heating_type == HeatingType.heatpump: + self._current_action = self._api.getCompressorActive() - self._attributes["return_temperature"] = self._api.getReturnTemperature() + self._attributes[ + "return_temperature" + ] = self._api.getReturnTemperature() + except requests.exceptions.ConnectionError: + _LOGGER.error("Unable to retrieve data from ViCare server") + except simplejson.errors.JSONDecodeError: + _LOGGER.error("Unable to decode data from ViCare server") @property def supported_features(self): diff --git a/homeassistant/components/vicare/water_heater.py b/homeassistant/components/vicare/water_heater.py index 7c4968ad0a4..1f56c46dc1c 100644 --- a/homeassistant/components/vicare/water_heater.py +++ b/homeassistant/components/vicare/water_heater.py @@ -1,5 +1,7 @@ """Viessmann ViCare water_heater device.""" import logging +import requests +import simplejson from homeassistant.components.water_heater import ( SUPPORT_TARGET_TEMPERATURE, @@ -41,6 +43,8 @@ HA_TO_VICARE_HVAC_DHW = { OPERATION_MODE_ON: VICARE_MODE_DHW, } +PYVICARE_ERROR = "error" + def setup_platform(hass, config, add_entities, discovery_info=None): """Create the ViCare water_heater devices.""" @@ -75,15 +79,22 @@ class ViCareWater(WaterHeaterDevice): def update(self): """Let HA know there has been an update from the ViCare API.""" - current_temperature = self._api.getDomesticHotWaterStorageTemperature() - if current_temperature is not None and current_temperature != "error": - self._current_temperature = current_temperature - else: - self._current_temperature = None + try: + current_temperature = self._api.getDomesticHotWaterStorageTemperature() + if current_temperature != PYVICARE_ERROR: + self._current_temperature = current_temperature + else: + self._current_temperature = None - self._target_temperature = self._api.getDomesticHotWaterConfiguredTemperature() + self._target_temperature = ( + self._api.getDomesticHotWaterConfiguredTemperature() + ) - self._current_mode = self._api.getActiveMode() + self._current_mode = self._api.getActiveMode() + except requests.exceptions.ConnectionError: + _LOGGER.error("Unable to retrieve data from ViCare server") + except simplejson.errors.JSONDecodeError: + _LOGGER.error("Unable to decode data from ViCare server") @property def supported_features(self):