diff --git a/homeassistant/components/screenlogic/__init__.py b/homeassistant/components/screenlogic/__init__.py index 4189158b178..11f71cfd337 100644 --- a/homeassistant/components/screenlogic/__init__.py +++ b/homeassistant/components/screenlogic/__init__.py @@ -60,8 +60,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): _LOGGER.error("Error while connecting to the gateway %s: %s", connect_info, ex) raise ConfigEntryNotReady from ex + # The api library uses a shared socket connection and does not handle concurrent + # requests very well. + api_lock = asyncio.Lock() + coordinator = ScreenlogicDataUpdateCoordinator( - hass, config_entry=entry, gateway=gateway + hass, config_entry=entry, gateway=gateway, api_lock=api_lock ) device_data = defaultdict(list) @@ -127,10 +131,11 @@ async def async_update_listener(hass: HomeAssistant, entry: ConfigEntry): class ScreenlogicDataUpdateCoordinator(DataUpdateCoordinator): """Class to manage the data update for the Screenlogic component.""" - def __init__(self, hass, *, config_entry, gateway): + def __init__(self, hass, *, config_entry, gateway, api_lock): """Initialize the Screenlogic Data Update Coordinator.""" self.config_entry = config_entry self.gateway = gateway + self.api_lock = api_lock self.screenlogic_data = {} interval = timedelta( seconds=config_entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) @@ -145,7 +150,8 @@ class ScreenlogicDataUpdateCoordinator(DataUpdateCoordinator): async def _async_update_data(self): """Fetch data from the Screenlogic gateway.""" try: - await self.hass.async_add_executor_job(self.gateway.update) + async with self.api_lock: + await self.hass.async_add_executor_job(self.gateway.update) except ScreenLogicError as error: raise UpdateFailed(error) from error return self.gateway.get_data() diff --git a/homeassistant/components/screenlogic/climate.py b/homeassistant/components/screenlogic/climate.py index d289c00228c..b50879bfd49 100644 --- a/homeassistant/components/screenlogic/climate.py +++ b/homeassistant/components/screenlogic/climate.py @@ -138,9 +138,12 @@ class ScreenLogicClimate(ScreenlogicEntity, ClimateEntity, RestoreEntity): if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None: raise ValueError(f"Expected attribute {ATTR_TEMPERATURE}") - if await self.hass.async_add_executor_job( - self.gateway.set_heat_temp, int(self._data_key), int(temperature) - ): + async with self.coordinator.api_lock: + success = await self.hass.async_add_executor_job( + self.gateway.set_heat_temp, int(self._data_key), int(temperature) + ) + + if success: await self.coordinator.async_request_refresh() else: raise HomeAssistantError( @@ -153,9 +156,13 @@ class ScreenLogicClimate(ScreenlogicEntity, ClimateEntity, RestoreEntity): mode = HEAT_MODE.OFF else: mode = HEAT_MODE.NUM_FOR_NAME[self.preset_mode] - if await self.hass.async_add_executor_job( - self.gateway.set_heat_mode, int(self._data_key), int(mode) - ): + + async with self.coordinator.api_lock: + success = await self.hass.async_add_executor_job( + self.gateway.set_heat_mode, int(self._data_key), int(mode) + ) + + if success: await self.coordinator.async_request_refresh() else: raise HomeAssistantError( @@ -168,9 +175,13 @@ class ScreenLogicClimate(ScreenlogicEntity, ClimateEntity, RestoreEntity): self._last_preset = mode = HEAT_MODE.NUM_FOR_NAME[preset_mode] if self.hvac_mode == HVAC_MODE_OFF: return - if await self.hass.async_add_executor_job( - self.gateway.set_heat_mode, int(self._data_key), int(mode) - ): + + async with self.coordinator.api_lock: + success = await self.hass.async_add_executor_job( + self.gateway.set_heat_mode, int(self._data_key), int(mode) + ) + + if success: await self.coordinator.async_request_refresh() else: raise HomeAssistantError( diff --git a/homeassistant/components/screenlogic/switch.py b/homeassistant/components/screenlogic/switch.py index d1ef9397bfc..e0077b1d62d 100644 --- a/homeassistant/components/screenlogic/switch.py +++ b/homeassistant/components/screenlogic/switch.py @@ -44,9 +44,12 @@ class ScreenLogicSwitch(ScreenlogicEntity, SwitchEntity): return await self._async_set_circuit(ON_OFF.OFF) async def _async_set_circuit(self, circuit_value) -> None: - if await self.hass.async_add_executor_job( - self.gateway.set_circuit, self._data_key, circuit_value - ): + async with self.coordinator.api_lock: + success = await self.hass.async_add_executor_job( + self.gateway.set_circuit, self._data_key, circuit_value + ) + + if success: _LOGGER.debug("Turn %s %s", self._data_key, circuit_value) await self.coordinator.async_request_refresh() else: