1 """Support for Ubiquiti's UniFi Protect NVR."""
3 from __future__
import annotations
5 from collections.abc
import Sequence
6 from dataclasses
import dataclass
7 from functools
import partial
9 from typing
import TYPE_CHECKING, Final
11 from uiprotect.data
import ModelType, ProtectAdoptableDeviceModel
16 ButtonEntityDescription,
24 from .const
import DEVICES_THAT_ADOPT, DOMAIN
25 from .data
import ProtectDeviceType, UFPConfigEntry
29 ProtectEntityDescription,
30 ProtectSetableKeysMixin,
32 async_all_device_entities,
35 _LOGGER = logging.getLogger(__name__)
38 @dataclass(frozen=True, kw_only=True)
40 ProtectSetableKeysMixin[T], ButtonEntityDescription
42 """Describes UniFi Protect Button entity."""
44 ufp_press: str |
None =
None
47 DEVICE_CLASS_CHIME_BUTTON: Final =
"unifiprotect__chime_button"
50 ALL_DEVICE_BUTTONS: tuple[ProtectButtonEntityDescription, ...] = (
53 entity_registry_enabled_default=
False,
54 device_class=ButtonDeviceClass.RESTART,
57 ufp_perm=PermRequired.WRITE,
61 entity_registry_enabled_default=
False,
62 name=
"Unadopt device",
65 ufp_perm=PermRequired.DELETE,
69 ADOPT_BUTTON = ProtectButtonEntityDescription[ProtectAdoptableDeviceModel](
72 icon=
"mdi:plus-circle",
76 SENSOR_BUTTONS: tuple[ProtectButtonEntityDescription, ...] = (
80 icon=
"mdi:notification-clear-all",
81 ufp_press=
"clear_tamper",
82 ufp_perm=PermRequired.WRITE,
86 CHIME_BUTTONS: tuple[ProtectButtonEntityDescription, ...] = (
90 device_class=DEVICE_CLASS_CHIME_BUTTON,
98 ufp_press=
"play_buzzer",
103 _MODEL_DESCRIPTIONS: dict[ModelType, Sequence[ProtectEntityDescription]] = {
104 ModelType.CHIME: CHIME_BUTTONS,
105 ModelType.SENSOR: SENSOR_BUTTONS,
111 hass: HomeAssistant, device: ProtectAdoptableDeviceModel
113 entity_registry = er.async_get(hass)
114 if entity_id := entity_registry.async_get_entity_id(
115 Platform.BUTTON, DOMAIN, f
"{device.mac}_adopt"
117 entity_registry.async_remove(entity_id)
122 entry: UFPConfigEntry,
123 async_add_entities: AddEntitiesCallback,
125 """Discover devices on a UniFi Protect NVR."""
126 data = entry.runtime_data
128 adopt_entities = partial(
129 async_all_device_entities,
132 unadopted_descs=[ADOPT_BUTTON],
134 base_entities = partial(
135 async_all_device_entities,
138 all_descs=ALL_DEVICE_BUTTONS,
139 model_descriptions=_MODEL_DESCRIPTIONS,
143 def _add_new_device(device: ProtectAdoptableDeviceModel) ->
None:
145 [*base_entities(ufp_device=device), *adopt_entities(ufp_device=device)]
150 def _async_add_unadopted_device(device: ProtectAdoptableDeviceModel) ->
None:
151 if not device.can_adopt
or not device.can_create(data.api.bootstrap.auth_user):
152 _LOGGER.debug(
"Device is not adoptable: %s", device.id)
156 data.async_subscribe_adopt(_add_new_device)
157 entry.async_on_unload(
162 for device
in data.get_by_types(DEVICES_THAT_ADOPT):
167 """A Ubiquiti UniFi Protect Reboot button."""
169 entity_description: ProtectButtonEntityDescription
172 """Press the button."""
178 """A Ubiquiti UniFi Protect Adopt button."""
184 assert isinstance(device, ProtectAdoptableDeviceModel)
186 self.
datadata.api.bootstrap.auth_user
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)