diff --git a/homeassistant/components/sensibo/climate.py b/homeassistant/components/sensibo/climate.py index 10ceaa39a38..d34ea040cdc 100644 --- a/homeassistant/components/sensibo/climate.py +++ b/homeassistant/components/sensibo/climate.py @@ -40,7 +40,7 @@ from .const import DOMAIN as SENSIBO_DOMAIN _LOGGER = logging.getLogger(__name__) ALL = ["all"] -TIMEOUT = 10 +TIMEOUT = 8 SERVICE_ASSUME_STATE = "assume_state" @@ -91,17 +91,18 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= ) devices = [] try: - for dev in await client.async_get_devices(_INITIAL_FETCH_FIELDS): - if config[CONF_ID] == ALL or dev["id"] in config[CONF_ID]: - devices.append( - SensiboClimate(client, dev, hass.config.units.temperature_unit) - ) + with async_timeout.timeout(TIMEOUT): + for dev in await client.async_get_devices(_INITIAL_FETCH_FIELDS): + if config[CONF_ID] == ALL or dev["id"] in config[CONF_ID]: + devices.append( + SensiboClimate(client, dev, hass.config.units.temperature_unit) + ) except ( aiohttp.client_exceptions.ClientConnectorError, asyncio.TimeoutError, pysensibo.SensiboError, ) as err: - _LOGGER.exception("Failed to connect to Sensibo servers") + _LOGGER.error("Failed to get devices from Sensibo servers") raise PlatformNotReady from err if not devices: @@ -150,6 +151,7 @@ class SensiboClimate(ClimateEntity): self._units = units self._available = False self._do_update(data) + self._failed_update = False @property def supported_features(self): @@ -316,59 +318,35 @@ class SensiboClimate(ClimateEntity): else: return - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "targetTemperature", temperature, self._ac_states - ) + await self._async_set_ac_state_property("targetTemperature", temperature) async def async_set_fan_mode(self, fan_mode): """Set new target fan mode.""" - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "fanLevel", fan_mode, self._ac_states - ) + await self._async_set_ac_state_property("fanLevel", fan_mode) async def async_set_hvac_mode(self, hvac_mode): """Set new target operation mode.""" if hvac_mode == HVAC_MODE_OFF: - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "on", False, self._ac_states - ) + await self._async_set_ac_state_property("on", False) return # Turn on if not currently on. if not self._ac_states["on"]: - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "on", True, self._ac_states - ) + await self._async_set_ac_state_property("on", True) - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "mode", HA_TO_SENSIBO[hvac_mode], self._ac_states - ) + await self._async_set_ac_state_property("mode", HA_TO_SENSIBO[hvac_mode]) async def async_set_swing_mode(self, swing_mode): """Set new target swing operation.""" - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "swing", swing_mode, self._ac_states - ) + await self._async_set_ac_state_property("swing", swing_mode) async def async_turn_on(self): """Turn Sensibo unit on.""" - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "on", True, self._ac_states - ) + await self._async_set_ac_state_property("on", True) async def async_turn_off(self): """Turn Sensibo unit on.""" - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, "on", False, self._ac_states - ) + await self._async_set_ac_state_property("on", False) async def async_assume_state(self, state): """Set external state.""" @@ -377,14 +355,7 @@ class SensiboClimate(ClimateEntity): ) if change_needed: - with async_timeout.timeout(TIMEOUT): - await self._client.async_set_ac_state_property( - self._id, - "on", - state != HVAC_MODE_OFF, # value - self._ac_states, - True, # assumed_state - ) + await self._async_set_ac_state_property("on", state != HVAC_MODE_OFF, True) if state in [STATE_ON, HVAC_MODE_OFF]: self._external_state = None @@ -396,7 +367,41 @@ class SensiboClimate(ClimateEntity): try: with async_timeout.timeout(TIMEOUT): data = await self._client.async_get_device(self._id, _FETCH_FIELDS) - self._do_update(data) - except (aiohttp.client_exceptions.ClientError, pysensibo.SensiboError): - _LOGGER.warning("Failed to connect to Sensibo servers") + except ( + aiohttp.client_exceptions.ClientError, + asyncio.TimeoutError, + pysensibo.SensiboError, + ): + if self._failed_update: + _LOGGER.warning( + "Failed to update data for device '%s' from Sensibo servers", + self.name, + ) + self._available = False + self.async_write_ha_state() + return + + _LOGGER.debug("First failed update data for device '%s'", self.name) + self._failed_update = True + return + + self._failed_update = False + self._do_update(data) + + async def _async_set_ac_state_property(self, name, value, assumed_state=False): + """Set AC state.""" + try: + with async_timeout.timeout(TIMEOUT): + await self._client.async_set_ac_state_property( + self._id, name, value, self._ac_states, assumed_state + ) + except ( + aiohttp.client_exceptions.ClientError, + asyncio.TimeoutError, + pysensibo.SensiboError, + ) as err: self._available = False + self.async_write_ha_state() + raise Exception( + f"Failed to set AC state for device {self.name} to Sensibo servers" + ) from err