1 """Button for Shelly."""
3 from __future__
import annotations
5 from collections.abc
import Callable, Coroutine
6 from dataclasses
import dataclass
7 from functools
import partial
8 from typing
import TYPE_CHECKING, Any, Final
10 from aioshelly.const
import RPC_GENERATIONS
15 ButtonEntityDescription,
25 from .const
import LOGGER, SHELLY_GAS_MODELS
26 from .coordinator
import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator
27 from .utils
import get_device_entry_gen
30 @dataclass(frozen=True, kw_only=True)
32 _ShellyCoordinatorT: ShellyBlockCoordinator | ShellyRpcCoordinator
33 ](ButtonEntityDescription):
34 """Class to describe a Button entity."""
36 press_action: Callable[[_ShellyCoordinatorT], Coroutine[Any, Any,
None]]
38 supported: Callable[[_ShellyCoordinatorT], bool] =
lambda _:
True
41 BUTTONS: Final[list[ShellyButtonDescription[Any]]] = [
42 ShellyButtonDescription[ShellyBlockCoordinator | ShellyRpcCoordinator](
45 device_class=ButtonDeviceClass.RESTART,
46 entity_category=EntityCategory.CONFIG,
47 press_action=
lambda coordinator: coordinator.device.trigger_reboot(),
49 ShellyButtonDescription[ShellyBlockCoordinator](
52 translation_key=
"self_test",
53 entity_category=EntityCategory.DIAGNOSTIC,
54 press_action=
lambda coordinator: coordinator.device.trigger_shelly_gas_self_test(),
55 supported=
lambda coordinator: coordinator.device.model
in SHELLY_GAS_MODELS,
57 ShellyButtonDescription[ShellyBlockCoordinator](
60 translation_key=
"mute",
61 entity_category=EntityCategory.CONFIG,
62 press_action=
lambda coordinator: coordinator.device.trigger_shelly_gas_mute(),
63 supported=
lambda coordinator: coordinator.device.model
in SHELLY_GAS_MODELS,
65 ShellyButtonDescription[ShellyBlockCoordinator](
68 translation_key=
"unmute",
69 entity_category=EntityCategory.CONFIG,
70 press_action=
lambda coordinator: coordinator.device.trigger_shelly_gas_unmute(),
71 supported=
lambda coordinator: coordinator.device.model
in SHELLY_GAS_MODELS,
78 coordinator: ShellyRpcCoordinator | ShellyBlockCoordinator,
79 entity_entry: er.RegistryEntry,
80 ) -> dict[str, Any] |
None:
81 """Migrate button unique IDs."""
82 if not entity_entry.entity_id.startswith(
"button"):
85 device_name =
slugify(coordinator.device.name)
87 for key
in (
"reboot",
"self_test",
"mute",
"unmute"):
88 old_unique_id = f
"{device_name}_{key}"
89 if entity_entry.unique_id == old_unique_id:
90 new_unique_id = f
"{coordinator.mac}_{key}"
92 "Migrating unique_id for %s entity from [%s] to [%s]",
93 entity_entry.entity_id,
98 "new_unique_id": entity_entry.unique_id.replace(
99 old_unique_id, new_unique_id
108 config_entry: ShellyConfigEntry,
109 async_add_entities: AddEntitiesCallback,
111 """Set buttons for device."""
112 entry_data = config_entry.runtime_data
113 coordinator: ShellyRpcCoordinator | ShellyBlockCoordinator |
None
115 coordinator = entry_data.rpc
117 coordinator = entry_data.block
120 assert coordinator
is not None
122 await er.async_migrate_entries(
123 hass, config_entry.entry_id, partial(async_migrate_unique_ids, coordinator)
128 for button
in BUTTONS
129 if button.supported(coordinator)
134 CoordinatorEntity[ShellyRpcCoordinator | ShellyBlockCoordinator], ButtonEntity
136 """Defines a Shelly base button."""
138 entity_description: ShellyButtonDescription[
139 ShellyRpcCoordinator | ShellyBlockCoordinator
144 coordinator: ShellyRpcCoordinator | ShellyBlockCoordinator,
145 description: ShellyButtonDescription[
146 ShellyRpcCoordinator | ShellyBlockCoordinator
149 """Initialize Shelly button."""
153 self.
_attr_name_attr_name = f
"{coordinator.device.name} {description.name}"
156 connections={(CONNECTION_NETWORK_MAC, coordinator.mac)}
160 """Triggers the Shelly button press service."""
int get_device_entry_gen(ConfigEntry entry)