Add asyncio locks to screenlogic api access points (#48457)
This commit is contained in:
parent
c1d5638739
commit
42a060ad33
3 changed files with 35 additions and 15 deletions
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue