mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 17:57:55 +00:00
Replace Guardian reboot
and reset_valve_diagnostics
services with buttons (#75028)
This commit is contained in:
parent
d40978742c
commit
b54fe14a10
@ -450,6 +450,7 @@ omit =
|
||||
homeassistant/components/gtfs/sensor.py
|
||||
homeassistant/components/guardian/__init__.py
|
||||
homeassistant/components/guardian/binary_sensor.py
|
||||
homeassistant/components/guardian/button.py
|
||||
homeassistant/components/guardian/sensor.py
|
||||
homeassistant/components/guardian/switch.py
|
||||
homeassistant/components/guardian/util.py
|
||||
|
@ -88,8 +88,7 @@ SERVICE_UPGRADE_FIRMWARE_SCHEMA = vol.Schema(
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR, Platform.SWITCH]
|
||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.SENSOR, Platform.SWITCH]
|
||||
|
||||
|
||||
@callback
|
||||
@ -106,6 +105,25 @@ def async_get_entry_id_for_service_call(hass: HomeAssistant, call: ServiceCall)
|
||||
raise ValueError(f"No client for device ID: {device_id}")
|
||||
|
||||
|
||||
@callback
|
||||
def async_log_deprecated_service_call(
|
||||
hass: HomeAssistant,
|
||||
call: ServiceCall,
|
||||
alternate_service: str,
|
||||
alternate_target: str,
|
||||
) -> None:
|
||||
"""Log a warning about a deprecated service call."""
|
||||
LOGGER.warning(
|
||||
(
|
||||
'The "%s" service is deprecated and will be removed in a future version; '
|
||||
'use the "%s" service and pass it a target entity ID of "%s"'
|
||||
),
|
||||
f"{call.domain}.{call.service}",
|
||||
alternate_service,
|
||||
alternate_target,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up Elexa Guardian from a config entry."""
|
||||
client = Client(entry.data[CONF_IP_ADDRESS], port=entry.data[CONF_PORT])
|
||||
@ -164,17 +182,19 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
@callback
|
||||
def extract_client(func: Callable) -> Callable:
|
||||
"""Define a decorator to get the correct client for a service call."""
|
||||
def hydrate_with_entry_and_client(func: Callable) -> Callable:
|
||||
"""Define a decorator to hydrate a method with args based on service call."""
|
||||
|
||||
async def wrapper(call: ServiceCall) -> None:
|
||||
"""Wrap the service function."""
|
||||
entry_id = async_get_entry_id_for_service_call(hass, call)
|
||||
client = hass.data[DOMAIN][entry_id][DATA_CLIENT]
|
||||
entry = hass.config_entries.async_get_entry(entry_id)
|
||||
assert entry
|
||||
|
||||
try:
|
||||
async with client:
|
||||
await func(call, client)
|
||||
await func(call, entry, client)
|
||||
except GuardianError as err:
|
||||
raise HomeAssistantError(
|
||||
f"Error while executing {func.__name__}: {err}"
|
||||
@ -182,48 +202,76 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
|
||||
return wrapper
|
||||
|
||||
@extract_client
|
||||
async def async_disable_ap(call: ServiceCall, client: Client) -> None:
|
||||
@hydrate_with_entry_and_client
|
||||
async def async_disable_ap(
|
||||
call: ServiceCall, entry: ConfigEntry, client: Client
|
||||
) -> None:
|
||||
"""Disable the onboard AP."""
|
||||
await client.wifi.disable_ap()
|
||||
|
||||
@extract_client
|
||||
async def async_enable_ap(call: ServiceCall, client: Client) -> None:
|
||||
@hydrate_with_entry_and_client
|
||||
async def async_enable_ap(
|
||||
call: ServiceCall, entry: ConfigEntry, client: Client
|
||||
) -> None:
|
||||
"""Enable the onboard AP."""
|
||||
await client.wifi.enable_ap()
|
||||
|
||||
@extract_client
|
||||
async def async_pair_sensor(call: ServiceCall, client: Client) -> None:
|
||||
@hydrate_with_entry_and_client
|
||||
async def async_pair_sensor(
|
||||
call: ServiceCall, entry: ConfigEntry, client: Client
|
||||
) -> None:
|
||||
"""Add a new paired sensor."""
|
||||
entry_id = async_get_entry_id_for_service_call(hass, call)
|
||||
paired_sensor_manager = hass.data[DOMAIN][entry_id][DATA_PAIRED_SENSOR_MANAGER]
|
||||
paired_sensor_manager = hass.data[DOMAIN][entry.entry_id][
|
||||
DATA_PAIRED_SENSOR_MANAGER
|
||||
]
|
||||
uid = call.data[CONF_UID]
|
||||
|
||||
await client.sensor.pair_sensor(uid)
|
||||
await paired_sensor_manager.async_pair_sensor(uid)
|
||||
|
||||
@extract_client
|
||||
async def async_reboot(call: ServiceCall, client: Client) -> None:
|
||||
@hydrate_with_entry_and_client
|
||||
async def async_reboot(
|
||||
call: ServiceCall, entry: ConfigEntry, client: Client
|
||||
) -> None:
|
||||
"""Reboot the valve controller."""
|
||||
async_log_deprecated_service_call(
|
||||
hass,
|
||||
call,
|
||||
"button.press",
|
||||
f"button.guardian_valve_controller_{entry.data[CONF_UID]}_reboot",
|
||||
)
|
||||
await client.system.reboot()
|
||||
|
||||
@extract_client
|
||||
async def async_reset_valve_diagnostics(call: ServiceCall, client: Client) -> None:
|
||||
@hydrate_with_entry_and_client
|
||||
async def async_reset_valve_diagnostics(
|
||||
call: ServiceCall, entry: ConfigEntry, client: Client
|
||||
) -> None:
|
||||
"""Fully reset system motor diagnostics."""
|
||||
async_log_deprecated_service_call(
|
||||
hass,
|
||||
call,
|
||||
"button.press",
|
||||
f"button.guardian_valve_controller_{entry.data[CONF_UID]}_reset_valve_diagnostics",
|
||||
)
|
||||
await client.valve.reset()
|
||||
|
||||
@extract_client
|
||||
async def async_unpair_sensor(call: ServiceCall, client: Client) -> None:
|
||||
@hydrate_with_entry_and_client
|
||||
async def async_unpair_sensor(
|
||||
call: ServiceCall, entry: ConfigEntry, client: Client
|
||||
) -> None:
|
||||
"""Remove a paired sensor."""
|
||||
entry_id = async_get_entry_id_for_service_call(hass, call)
|
||||
paired_sensor_manager = hass.data[DOMAIN][entry_id][DATA_PAIRED_SENSOR_MANAGER]
|
||||
paired_sensor_manager = hass.data[DOMAIN][entry.entry_id][
|
||||
DATA_PAIRED_SENSOR_MANAGER
|
||||
]
|
||||
uid = call.data[CONF_UID]
|
||||
|
||||
await client.sensor.unpair_sensor(uid)
|
||||
await paired_sensor_manager.async_unpair_sensor(uid)
|
||||
|
||||
@extract_client
|
||||
async def async_upgrade_firmware(call: ServiceCall, client: Client) -> None:
|
||||
@hydrate_with_entry_and_client
|
||||
async def async_upgrade_firmware(
|
||||
call: ServiceCall, entry: ConfigEntry, client: Client
|
||||
) -> None:
|
||||
"""Upgrade the device firmware."""
|
||||
await client.system.upgrade_firmware(
|
||||
url=call.data[CONF_URL],
|
||||
@ -389,7 +437,6 @@ class GuardianEntity(CoordinatorEntity):
|
||||
|
||||
This should be extended by Guardian platforms.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class PairedSensorEntity(GuardianEntity):
|
||||
@ -454,7 +501,6 @@ class ValveControllerEntity(GuardianEntity):
|
||||
|
||||
This should be extended by Guardian platforms.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@callback
|
||||
def async_add_coordinator_update_listener(self, api: str) -> None:
|
||||
|
113
homeassistant/components/guardian/button.py
Normal file
113
homeassistant/components/guardian/button.py
Normal file
@ -0,0 +1,113 @@
|
||||
"""Buttons for the Elexa Guardian integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from aioguardian import Client
|
||||
from aioguardian.errors import GuardianError
|
||||
|
||||
from homeassistant.components.button import (
|
||||
ButtonDeviceClass,
|
||||
ButtonEntity,
|
||||
ButtonEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
from . import ValveControllerEntity
|
||||
from .const import DATA_CLIENT, DATA_COORDINATOR, DOMAIN
|
||||
|
||||
|
||||
@dataclass
|
||||
class GuardianButtonDescriptionMixin:
|
||||
"""Define an entity description mixin for Guardian buttons."""
|
||||
|
||||
push_action: Callable[[Client], Awaitable]
|
||||
|
||||
|
||||
@dataclass
|
||||
class GuardianButtonDescription(
|
||||
ButtonEntityDescription, GuardianButtonDescriptionMixin
|
||||
):
|
||||
"""Describe a Guardian button description."""
|
||||
|
||||
|
||||
BUTTON_KIND_REBOOT = "reboot"
|
||||
BUTTON_KIND_RESET_VALVE_DIAGNOSTICS = "reset_valve_diagnostics"
|
||||
|
||||
|
||||
async def _async_reboot(client: Client) -> None:
|
||||
"""Reboot the Guardian."""
|
||||
await client.system.reboot()
|
||||
|
||||
|
||||
async def _async_valve_reset(client: Client) -> None:
|
||||
"""Reset the valve diagnostics on the Guardian."""
|
||||
await client.valve.reset()
|
||||
|
||||
|
||||
BUTTON_DESCRIPTIONS = (
|
||||
GuardianButtonDescription(
|
||||
key=BUTTON_KIND_REBOOT,
|
||||
name="Reboot",
|
||||
push_action=_async_reboot,
|
||||
),
|
||||
GuardianButtonDescription(
|
||||
key=BUTTON_KIND_RESET_VALVE_DIAGNOSTICS,
|
||||
name="Reset valve diagnostics",
|
||||
push_action=_async_valve_reset,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
"""Set up Guardian buttons based on a config entry."""
|
||||
async_add_entities(
|
||||
[
|
||||
GuardianButton(
|
||||
entry,
|
||||
hass.data[DOMAIN][entry.entry_id][DATA_CLIENT],
|
||||
hass.data[DOMAIN][entry.entry_id][DATA_COORDINATOR],
|
||||
description,
|
||||
)
|
||||
for description in BUTTON_DESCRIPTIONS
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class GuardianButton(ValveControllerEntity, ButtonEntity):
|
||||
"""Define a Guardian button."""
|
||||
|
||||
_attr_device_class = ButtonDeviceClass.RESTART
|
||||
_attr_entity_category = EntityCategory.CONFIG
|
||||
|
||||
entity_description: GuardianButtonDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
entry: ConfigEntry,
|
||||
client: Client,
|
||||
coordinators: dict[str, DataUpdateCoordinator],
|
||||
description: GuardianButtonDescription,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
super().__init__(entry, coordinators, description)
|
||||
|
||||
self._client = client
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Send out a restart command."""
|
||||
try:
|
||||
async with self._client:
|
||||
await self.entity_description.push_action(self._client)
|
||||
except GuardianError as err:
|
||||
raise HomeAssistantError(
|
||||
f'Error while pressing button "{self.entity_id}": {err}'
|
||||
) from err
|
Loading…
x
Reference in New Issue
Block a user