Appropriately mark Guardian entities as unavailable
during reboot (#75234)
This commit is contained in:
parent
98293f2179
commit
a3bffdf523
5 changed files with 54 additions and 6 deletions
|
@ -137,6 +137,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
# so we use a lock to ensure that only one API request is reaching it at a time:
|
# so we use a lock to ensure that only one API request is reaching it at a time:
|
||||||
api_lock = asyncio.Lock()
|
api_lock = asyncio.Lock()
|
||||||
|
|
||||||
|
async def async_init_coordinator(
|
||||||
|
coordinator: GuardianDataUpdateCoordinator,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize a GuardianDataUpdateCoordinator."""
|
||||||
|
await coordinator.async_initialize()
|
||||||
|
await coordinator.async_config_entry_first_refresh()
|
||||||
|
|
||||||
# Set up GuardianDataUpdateCoordinators for the valve controller:
|
# Set up GuardianDataUpdateCoordinators for the valve controller:
|
||||||
valve_controller_coordinators: dict[str, GuardianDataUpdateCoordinator] = {}
|
valve_controller_coordinators: dict[str, GuardianDataUpdateCoordinator] = {}
|
||||||
init_valve_controller_tasks = []
|
init_valve_controller_tasks = []
|
||||||
|
@ -151,13 +158,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
api
|
api
|
||||||
] = GuardianDataUpdateCoordinator(
|
] = GuardianDataUpdateCoordinator(
|
||||||
hass,
|
hass,
|
||||||
|
entry=entry,
|
||||||
client=client,
|
client=client,
|
||||||
api_name=api,
|
api_name=api,
|
||||||
api_coro=api_coro,
|
api_coro=api_coro,
|
||||||
api_lock=api_lock,
|
api_lock=api_lock,
|
||||||
valve_controller_uid=entry.data[CONF_UID],
|
valve_controller_uid=entry.data[CONF_UID],
|
||||||
)
|
)
|
||||||
init_valve_controller_tasks.append(coordinator.async_refresh())
|
init_valve_controller_tasks.append(async_init_coordinator(coordinator))
|
||||||
|
|
||||||
await asyncio.gather(*init_valve_controller_tasks)
|
await asyncio.gather(*init_valve_controller_tasks)
|
||||||
|
|
||||||
|
@ -352,6 +360,7 @@ class PairedSensorManager:
|
||||||
|
|
||||||
coordinator = self.coordinators[uid] = GuardianDataUpdateCoordinator(
|
coordinator = self.coordinators[uid] = GuardianDataUpdateCoordinator(
|
||||||
self._hass,
|
self._hass,
|
||||||
|
entry=self._entry,
|
||||||
client=self._client,
|
client=self._client,
|
||||||
api_name=f"{API_SENSOR_PAIRED_SENSOR_STATUS}_{uid}",
|
api_name=f"{API_SENSOR_PAIRED_SENSOR_STATUS}_{uid}",
|
||||||
api_coro=lambda: cast(
|
api_coro=lambda: cast(
|
||||||
|
@ -422,7 +431,7 @@ class GuardianEntity(CoordinatorEntity[GuardianDataUpdateCoordinator]):
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_from_latest_data(self) -> None:
|
def _async_update_from_latest_data(self) -> None:
|
||||||
"""Update the entity.
|
"""Update the entity's underlying data.
|
||||||
|
|
||||||
This should be extended by Guardian platforms.
|
This should be extended by Guardian platforms.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -137,7 +137,7 @@ class PairedSensorBinarySensor(PairedSensorEntity, BinarySensorEntity):
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_from_latest_data(self) -> None:
|
def _async_update_from_latest_data(self) -> None:
|
||||||
"""Update the entity."""
|
"""Update the entity's underlying data."""
|
||||||
if self.entity_description.key == SENSOR_KIND_LEAK_DETECTED:
|
if self.entity_description.key == SENSOR_KIND_LEAK_DETECTED:
|
||||||
self._attr_is_on = self.coordinator.data["wet"]
|
self._attr_is_on = self.coordinator.data["wet"]
|
||||||
elif self.entity_description.key == SENSOR_KIND_MOVED:
|
elif self.entity_description.key == SENSOR_KIND_MOVED:
|
||||||
|
|
|
@ -15,6 +15,7 @@ from homeassistant.components.button import (
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
@ -111,3 +112,5 @@ class GuardianButton(ValveControllerEntity, ButtonEntity):
|
||||||
raise HomeAssistantError(
|
raise HomeAssistantError(
|
||||||
f'Error while pressing button "{self.entity_id}": {err}'
|
f'Error while pressing button "{self.entity_id}": {err}'
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
|
async_dispatcher_send(self.hass, self.coordinator.signal_reboot_requested)
|
||||||
|
|
|
@ -128,7 +128,7 @@ class PairedSensorSensor(PairedSensorEntity, SensorEntity):
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_from_latest_data(self) -> None:
|
def _async_update_from_latest_data(self) -> None:
|
||||||
"""Update the entity."""
|
"""Update the entity's underlying data."""
|
||||||
if self.entity_description.key == SENSOR_KIND_BATTERY:
|
if self.entity_description.key == SENSOR_KIND_BATTERY:
|
||||||
self._attr_native_value = self.coordinator.data["battery"]
|
self._attr_native_value = self.coordinator.data["battery"]
|
||||||
elif self.entity_description.key == SENSOR_KIND_TEMPERATURE:
|
elif self.entity_description.key == SENSOR_KIND_TEMPERATURE:
|
||||||
|
@ -142,7 +142,7 @@ class ValveControllerSensor(ValveControllerEntity, SensorEntity):
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_from_latest_data(self) -> None:
|
def _async_update_from_latest_data(self) -> None:
|
||||||
"""Update the entity."""
|
"""Update the entity's underlying data."""
|
||||||
if self.entity_description.key == SENSOR_KIND_TEMPERATURE:
|
if self.entity_description.key == SENSOR_KIND_TEMPERATURE:
|
||||||
self._attr_native_value = self.coordinator.data["temperature"]
|
self._attr_native_value = self.coordinator.data["temperature"]
|
||||||
elif self.entity_description.key == SENSOR_KIND_UPTIME:
|
elif self.entity_description.key == SENSOR_KIND_UPTIME:
|
||||||
|
|
|
@ -9,21 +9,28 @@ from typing import Any, cast
|
||||||
from aioguardian import Client
|
from aioguardian import Client
|
||||||
from aioguardian.errors import GuardianError
|
from aioguardian.errors import GuardianError
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import LOGGER
|
from .const import LOGGER
|
||||||
|
|
||||||
DEFAULT_UPDATE_INTERVAL = timedelta(seconds=30)
|
DEFAULT_UPDATE_INTERVAL = timedelta(seconds=30)
|
||||||
|
|
||||||
|
SIGNAL_REBOOT_REQUESTED = "guardian_reboot_requested_{0}"
|
||||||
|
|
||||||
|
|
||||||
class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]):
|
class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]):
|
||||||
"""Define an extended DataUpdateCoordinator with some Guardian goodies."""
|
"""Define an extended DataUpdateCoordinator with some Guardian goodies."""
|
||||||
|
|
||||||
|
config_entry: ConfigEntry
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
*,
|
*,
|
||||||
|
entry: ConfigEntry,
|
||||||
client: Client,
|
client: Client,
|
||||||
api_name: str,
|
api_name: str,
|
||||||
api_coro: Callable[..., Awaitable],
|
api_coro: Callable[..., Awaitable],
|
||||||
|
@ -41,6 +48,12 @@ class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]):
|
||||||
self._api_coro = api_coro
|
self._api_coro = api_coro
|
||||||
self._api_lock = api_lock
|
self._api_lock = api_lock
|
||||||
self._client = client
|
self._client = client
|
||||||
|
self._signal_handler_unsubs: list[Callable[..., None]] = []
|
||||||
|
|
||||||
|
self.config_entry = entry
|
||||||
|
self.signal_reboot_requested = SIGNAL_REBOOT_REQUESTED.format(
|
||||||
|
self.config_entry.entry_id
|
||||||
|
)
|
||||||
|
|
||||||
async def _async_update_data(self) -> dict[str, Any]:
|
async def _async_update_data(self) -> dict[str, Any]:
|
||||||
"""Execute a "locked" API request against the valve controller."""
|
"""Execute a "locked" API request against the valve controller."""
|
||||||
|
@ -50,3 +63,26 @@ class GuardianDataUpdateCoordinator(DataUpdateCoordinator[dict]):
|
||||||
except GuardianError as err:
|
except GuardianError as err:
|
||||||
raise UpdateFailed(err) from err
|
raise UpdateFailed(err) from err
|
||||||
return cast(dict[str, Any], resp["data"])
|
return cast(dict[str, Any], resp["data"])
|
||||||
|
|
||||||
|
async def async_initialize(self) -> None:
|
||||||
|
"""Initialize the coordinator."""
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_reboot_requested() -> None:
|
||||||
|
"""Respond to a reboot request."""
|
||||||
|
self.last_update_success = False
|
||||||
|
self.async_update_listeners()
|
||||||
|
|
||||||
|
self._signal_handler_unsubs.append(
|
||||||
|
async_dispatcher_connect(
|
||||||
|
self.hass, self.signal_reboot_requested, async_reboot_requested
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_teardown() -> None:
|
||||||
|
"""Tear the coordinator down appropriately."""
|
||||||
|
for unsub in self._signal_handler_unsubs:
|
||||||
|
unsub()
|
||||||
|
|
||||||
|
self.config_entry.async_on_unload(async_teardown)
|
||||||
|
|
Loading…
Add table
Reference in a new issue