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)
|
_LOGGER.error("Error while connecting to the gateway %s: %s", connect_info, ex)
|
||||||
raise ConfigEntryNotReady from 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(
|
coordinator = ScreenlogicDataUpdateCoordinator(
|
||||||
hass, config_entry=entry, gateway=gateway
|
hass, config_entry=entry, gateway=gateway, api_lock=api_lock
|
||||||
)
|
)
|
||||||
|
|
||||||
device_data = defaultdict(list)
|
device_data = defaultdict(list)
|
||||||
|
@ -127,10 +131,11 @@ async def async_update_listener(hass: HomeAssistant, entry: ConfigEntry):
|
||||||
class ScreenlogicDataUpdateCoordinator(DataUpdateCoordinator):
|
class ScreenlogicDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
"""Class to manage the data update for the Screenlogic component."""
|
"""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."""
|
"""Initialize the Screenlogic Data Update Coordinator."""
|
||||||
self.config_entry = config_entry
|
self.config_entry = config_entry
|
||||||
self.gateway = gateway
|
self.gateway = gateway
|
||||||
|
self.api_lock = api_lock
|
||||||
self.screenlogic_data = {}
|
self.screenlogic_data = {}
|
||||||
interval = timedelta(
|
interval = timedelta(
|
||||||
seconds=config_entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
seconds=config_entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||||
|
@ -145,7 +150,8 @@ class ScreenlogicDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
async def _async_update_data(self):
|
async def _async_update_data(self):
|
||||||
"""Fetch data from the Screenlogic gateway."""
|
"""Fetch data from the Screenlogic gateway."""
|
||||||
try:
|
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:
|
except ScreenLogicError as error:
|
||||||
raise UpdateFailed(error) from error
|
raise UpdateFailed(error) from error
|
||||||
return self.gateway.get_data()
|
return self.gateway.get_data()
|
||||||
|
|
|
@ -138,9 +138,12 @@ class ScreenLogicClimate(ScreenlogicEntity, ClimateEntity, RestoreEntity):
|
||||||
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None:
|
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None:
|
||||||
raise ValueError(f"Expected attribute {ATTR_TEMPERATURE}")
|
raise ValueError(f"Expected attribute {ATTR_TEMPERATURE}")
|
||||||
|
|
||||||
if await self.hass.async_add_executor_job(
|
async with self.coordinator.api_lock:
|
||||||
self.gateway.set_heat_temp, int(self._data_key), int(temperature)
|
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()
|
await self.coordinator.async_request_refresh()
|
||||||
else:
|
else:
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
|
@ -153,9 +156,13 @@ class ScreenLogicClimate(ScreenlogicEntity, ClimateEntity, RestoreEntity):
|
||||||
mode = HEAT_MODE.OFF
|
mode = HEAT_MODE.OFF
|
||||||
else:
|
else:
|
||||||
mode = HEAT_MODE.NUM_FOR_NAME[self.preset_mode]
|
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()
|
await self.coordinator.async_request_refresh()
|
||||||
else:
|
else:
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
|
@ -168,9 +175,13 @@ class ScreenLogicClimate(ScreenlogicEntity, ClimateEntity, RestoreEntity):
|
||||||
self._last_preset = mode = HEAT_MODE.NUM_FOR_NAME[preset_mode]
|
self._last_preset = mode = HEAT_MODE.NUM_FOR_NAME[preset_mode]
|
||||||
if self.hvac_mode == HVAC_MODE_OFF:
|
if self.hvac_mode == HVAC_MODE_OFF:
|
||||||
return
|
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()
|
await self.coordinator.async_request_refresh()
|
||||||
else:
|
else:
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
|
|
|
@ -44,9 +44,12 @@ class ScreenLogicSwitch(ScreenlogicEntity, SwitchEntity):
|
||||||
return await self._async_set_circuit(ON_OFF.OFF)
|
return await self._async_set_circuit(ON_OFF.OFF)
|
||||||
|
|
||||||
async def _async_set_circuit(self, circuit_value) -> None:
|
async def _async_set_circuit(self, circuit_value) -> None:
|
||||||
if await self.hass.async_add_executor_job(
|
async with self.coordinator.api_lock:
|
||||||
self.gateway.set_circuit, self._data_key, circuit_value
|
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)
|
_LOGGER.debug("Turn %s %s", self._data_key, circuit_value)
|
||||||
await self.coordinator.async_request_refresh()
|
await self.coordinator.async_request_refresh()
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue