1 """Support for Homekit buttons.
3 These are mostly used where a HomeKit accessory exposes additional non-standard
4 characteristics that don't map to a Home Assistant feature.
7 from __future__
import annotations
9 from collections.abc
import Callable
10 from dataclasses
import dataclass
13 from aiohomekit.model.characteristics
import Characteristic, CharacteristicsTypes
18 ButtonEntityDescription,
26 from .
import KNOWN_DEVICES
27 from .connection
import HKDevice
28 from .entity
import CharacteristicEntity
30 _LOGGER = logging.getLogger(__name__)
33 @dataclass(frozen=True)
35 """Describes Homekit button."""
37 probe: Callable[[Characteristic], bool] |
None =
None
38 write_value: int | str |
None =
None
41 BUTTON_ENTITIES: dict[str, HomeKitButtonEntityDescription] = {
43 key=CharacteristicsTypes.VENDOR_HAA_SETUP,
45 translation_key=
"setup",
46 entity_category=EntityCategory.CONFIG,
47 write_value=
"#HAA@trcmd",
50 key=CharacteristicsTypes.VENDOR_HAA_UPDATE,
52 device_class=ButtonDeviceClass.UPDATE,
53 entity_category=EntityCategory.CONFIG,
54 write_value=
"#HAA@trcmd",
57 key=CharacteristicsTypes.IDENTIFY,
59 device_class=ButtonDeviceClass.IDENTIFY,
60 entity_category=EntityCategory.DIAGNOSTIC,
68 config_entry: ConfigEntry,
69 async_add_entities: AddEntitiesCallback,
71 """Set up Homekit buttons."""
72 hkid: str = config_entry.data[
"AccessoryPairingID"]
73 conn: HKDevice = hass.data[KNOWN_DEVICES][hkid]
77 entities: list[CharacteristicEntity] = []
78 info = {
"aid": char.service.accessory.aid,
"iid": char.service.iid}
80 if description := BUTTON_ENTITIES.get(char.type):
82 elif entity_type := BUTTON_ENTITY_CLASSES.get(char.type):
83 entities.append(entity_type(conn, info, char))
84 elif char.type == CharacteristicsTypes.THREAD_CONTROL_POINT:
85 if not conn.is_unprovisioned_thread_device:
93 for entity
in entities:
94 conn.async_migrate_unique_id(
95 entity.old_unique_id, entity.unique_id, Platform.BUTTON
101 conn.add_char_factory(async_add_characteristic)
105 """Base class for all HomeKit buttons."""
108 class HomeKitButton(BaseHomeKitButton):
109 """Representation of a Button control on a homekit accessory."""
111 entity_description: HomeKitButtonEntityDescription
117 char: Characteristic,
118 description: HomeKitButtonEntityDescription,
120 """Initialise a HomeKit button control."""
125 """Define the homekit characteristics the entity is tracking."""
126 return [self.
_char_char.type]
130 """Return the name of the device if any."""
132 return f
"{name} {self.entity_description.name}"
133 return f
"{self.entity_description.name}"
136 """Press the button."""
143 """Representation of a Button control for Ecobee clear hold request."""
146 """Define the homekit characteristics the entity is tracking."""
151 """Return the name of the device if any."""
153 if name := super().name:
155 return f
"{prefix} Clear Hold"
158 """Press the button."""
159 key = self.
_char_char.type
167 for val
in (
False,
True):
172 """A button users can press to migrate their HomeKit BLE device to Thread."""
174 _attr_entity_category = EntityCategory.CONFIG
177 """Define the homekit characteristics the entity is tracking."""
182 """Return the name of the device if any."""
184 if name := super().name:
186 return f
"{prefix} Provision Preferred Thread Credentials"
189 """Press the button."""
190 await self.
_accessory_accessory.async_thread_provision()
193 BUTTON_ENTITY_CLASSES: dict[str, type] = {
194 CharacteristicsTypes.VENDOR_ECOBEE_CLEAR_HOLD: HomeKitEcobeeClearHoldButton,
None async_put_characteristics(self, dict[str, Any] characteristics)
bool async_add_characteristic(Characteristic char)