diff --git a/homeassistant/components/hunterdouglas_powerview/button.py b/homeassistant/components/hunterdouglas_powerview/button.py index f7c90f3420b..ecb71f9653a 100644 --- a/homeassistant/components/hunterdouglas_powerview/button.py +++ b/homeassistant/components/hunterdouglas_powerview/button.py @@ -119,4 +119,5 @@ class PowerviewShadeButton(ShadeEntity, ButtonEntity): async def async_press(self) -> None: """Handle the button press.""" - await self.entity_description.press_action(self._shade) + async with self.coordinator.radio_operation_lock: + await self.entity_description.press_action(self._shade) diff --git a/homeassistant/components/hunterdouglas_powerview/coordinator.py b/homeassistant/components/hunterdouglas_powerview/coordinator.py index 1ea47ca9d1f..f074b06b2bc 100644 --- a/homeassistant/components/hunterdouglas_powerview/coordinator.py +++ b/homeassistant/components/hunterdouglas_powerview/coordinator.py @@ -2,6 +2,7 @@ from __future__ import annotations +import asyncio from datetime import timedelta import logging @@ -25,6 +26,10 @@ class PowerviewShadeUpdateCoordinator(DataUpdateCoordinator[PowerviewShadeData]) """Initialize DataUpdateCoordinator to gather data for specific Powerview Hub.""" self.shades = shades self.hub = hub + # The hub tends to crash if there are multiple radio operations at the same time + # but it seems to handle all other requests that do not use RF without issue + # so we have a lock to prevent multiple radio operations at the same time + self.radio_operation_lock = asyncio.Lock() super().__init__( hass, _LOGGER, diff --git a/homeassistant/components/hunterdouglas_powerview/cover.py b/homeassistant/components/hunterdouglas_powerview/cover.py index 453d5c4e920..57409f37ac9 100644 --- a/homeassistant/components/hunterdouglas_powerview/cover.py +++ b/homeassistant/components/hunterdouglas_powerview/cover.py @@ -67,7 +67,8 @@ async def async_setup_entry( for shade in pv_entry.shade_data.values(): _LOGGER.debug("Initial refresh of shade: %s", shade.name) - await shade.refresh(suppress_timeout=True) # default 15 second timeout + async with coordinator.radio_operation_lock: + await shade.refresh(suppress_timeout=True) # default 15 second timeout entities: list[ShadeEntity] = [] for shade in pv_entry.shade_data.values(): @@ -207,7 +208,8 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity): async def _async_execute_move(self, move: ShadePosition) -> None: """Execute a move that can affect multiple positions.""" _LOGGER.debug("Move request %s: %s", self.name, move) - response = await self._shade.move(move) + async with self.coordinator.radio_operation_lock: + response = await self._shade.move(move) _LOGGER.debug("Move response %s: %s", self.name, response) # Process the response from the hub (including new positions) @@ -318,7 +320,10 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity): # error if are already have one in flight return # suppress timeouts caused by hub nightly reboot - await self._shade.refresh(suppress_timeout=True) # default 15 second timeout + async with self.coordinator.radio_operation_lock: + await self._shade.refresh( + suppress_timeout=True + ) # default 15 second timeout _LOGGER.debug("Process update %s: %s", self.name, self._shade.current_position) self._async_update_shade_data(self._shade.current_position) diff --git a/homeassistant/components/hunterdouglas_powerview/select.py b/homeassistant/components/hunterdouglas_powerview/select.py index 66207f6da7c..f1e9c491659 100644 --- a/homeassistant/components/hunterdouglas_powerview/select.py +++ b/homeassistant/components/hunterdouglas_powerview/select.py @@ -114,5 +114,6 @@ class PowerViewSelect(ShadeEntity, SelectEntity): """Change the selected option.""" await self.entity_description.select_fn(self._shade, option) # force update data to ensure new info is in coordinator - await self._shade.refresh() + async with self.coordinator.radio_operation_lock: + await self._shade.refresh(suppress_timeout=True) self.async_write_ha_state() diff --git a/homeassistant/components/hunterdouglas_powerview/sensor.py b/homeassistant/components/hunterdouglas_powerview/sensor.py index bca87189e56..b24193ac438 100644 --- a/homeassistant/components/hunterdouglas_powerview/sensor.py +++ b/homeassistant/components/hunterdouglas_powerview/sensor.py @@ -153,5 +153,6 @@ class PowerViewSensor(ShadeEntity, SensorEntity): async def async_update(self) -> None: """Refresh sensor entity.""" - await self.entity_description.update_fn(self._shade) + async with self.coordinator.radio_operation_lock: + await self.entity_description.update_fn(self._shade) self.async_write_ha_state()