mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Cleanup unifiprotect entity classes (#121184)
This commit is contained in:
parent
22718ca32a
commit
d3f424227f
@ -8,11 +8,9 @@ import dataclasses
|
|||||||
from uiprotect.data import (
|
from uiprotect.data import (
|
||||||
NVR,
|
NVR,
|
||||||
Camera,
|
Camera,
|
||||||
Light,
|
|
||||||
ModelType,
|
ModelType,
|
||||||
MountType,
|
MountType,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
Sensor,
|
Sensor,
|
||||||
SmartDetectObjectType,
|
SmartDetectObjectType,
|
||||||
)
|
)
|
||||||
@ -27,11 +25,12 @@ from homeassistant.const import EntityCategory
|
|||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .data import ProtectData, UFPConfigEntry
|
from .data import ProtectData, ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import (
|
from .entity import (
|
||||||
BaseProtectEntity,
|
BaseProtectEntity,
|
||||||
EventEntityMixin,
|
EventEntityMixin,
|
||||||
ProtectDeviceEntity,
|
ProtectDeviceEntity,
|
||||||
|
ProtectIsOnEntity,
|
||||||
ProtectNVREntity,
|
ProtectNVREntity,
|
||||||
async_all_device_entities,
|
async_all_device_entities,
|
||||||
)
|
)
|
||||||
@ -623,31 +622,22 @@ _MOUNTABLE_MODEL_DESCRIPTIONS: dict[ModelType, Sequence[ProtectEntityDescription
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ProtectDeviceBinarySensor(ProtectDeviceEntity, BinarySensorEntity):
|
class ProtectDeviceBinarySensor(
|
||||||
|
ProtectIsOnEntity, ProtectDeviceEntity, BinarySensorEntity
|
||||||
|
):
|
||||||
"""A UniFi Protect Device Binary Sensor."""
|
"""A UniFi Protect Device Binary Sensor."""
|
||||||
|
|
||||||
device: Camera | Light | Sensor
|
|
||||||
entity_description: ProtectBinaryEntityDescription
|
entity_description: ProtectBinaryEntityDescription
|
||||||
_state_attrs: tuple[str, ...] = ("_attr_available", "_attr_is_on")
|
|
||||||
|
|
||||||
@callback
|
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
|
||||||
super()._async_update_device_from_protect(device)
|
|
||||||
self._attr_is_on = self.entity_description.get_ufp_value(self.device)
|
|
||||||
|
|
||||||
|
|
||||||
class MountableProtectDeviceBinarySensor(ProtectDeviceBinarySensor):
|
class MountableProtectDeviceBinarySensor(ProtectDeviceBinarySensor):
|
||||||
"""A UniFi Protect Device Binary Sensor that can change device class at runtime."""
|
"""A UniFi Protect Device Binary Sensor that can change device class at runtime."""
|
||||||
|
|
||||||
device: Sensor
|
device: Sensor
|
||||||
_state_attrs: tuple[str, ...] = (
|
_state_attrs = ("_attr_available", "_attr_is_on", "_attr_device_class")
|
||||||
"_attr_available",
|
|
||||||
"_attr_is_on",
|
|
||||||
"_attr_device_class",
|
|
||||||
)
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
# UP Sense can be any of the 3 contact sensor device classes
|
# UP Sense can be any of the 3 contact sensor device classes
|
||||||
self._attr_device_class = MOUNT_DEVICE_CLASS_MAP.get(
|
self._attr_device_class = MOUNT_DEVICE_CLASS_MAP.get(
|
||||||
@ -673,7 +663,6 @@ class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity):
|
|||||||
self._disk = disk
|
self._disk = disk
|
||||||
# backwards compat with old unique IDs
|
# backwards compat with old unique IDs
|
||||||
index = self._disk.slot - 1
|
index = self._disk.slot - 1
|
||||||
|
|
||||||
description = dataclasses.replace(
|
description = dataclasses.replace(
|
||||||
description,
|
description,
|
||||||
key=f"{description.key}_{index}",
|
key=f"{description.key}_{index}",
|
||||||
@ -682,7 +671,7 @@ class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity):
|
|||||||
super().__init__(data, device, description)
|
super().__init__(data, device, description)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
slot = self._disk.slot
|
slot = self._disk.slot
|
||||||
self._attr_available = False
|
self._attr_available = False
|
||||||
@ -712,7 +701,7 @@ class ProtectEventBinarySensor(EventEntityMixin, BinarySensorEntity):
|
|||||||
self._attr_extra_state_attributes = {}
|
self._attr_extra_state_attributes = {}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
description = self.entity_description
|
description = self.entity_description
|
||||||
|
|
||||||
prev_event = self._event
|
prev_event = self._event
|
||||||
|
@ -4,10 +4,11 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from functools import partial
|
||||||
import logging
|
import logging
|
||||||
from typing import Final
|
from typing import TYPE_CHECKING, Final
|
||||||
|
|
||||||
from uiprotect.data import ModelType, ProtectAdoptableDeviceModel, ProtectModelWithId
|
from uiprotect.data import ModelType, ProtectAdoptableDeviceModel
|
||||||
|
|
||||||
from homeassistant.components.button import (
|
from homeassistant.components.button import (
|
||||||
ButtonDeviceClass,
|
ButtonDeviceClass,
|
||||||
@ -21,7 +22,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DEVICES_THAT_ADOPT, DOMAIN
|
from .const import DEVICES_THAT_ADOPT, DOMAIN
|
||||||
from .data import UFPConfigEntry
|
from .data import ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity, async_all_device_entities
|
from .entity import ProtectDeviceEntity, async_all_device_entities
|
||||||
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
||||||
|
|
||||||
@ -38,7 +39,6 @@ class ProtectButtonEntityDescription(
|
|||||||
|
|
||||||
|
|
||||||
DEVICE_CLASS_CHIME_BUTTON: Final = "unifiprotect__chime_button"
|
DEVICE_CLASS_CHIME_BUTTON: Final = "unifiprotect__chime_button"
|
||||||
KEY_ADOPT = "adopt"
|
|
||||||
|
|
||||||
|
|
||||||
ALL_DEVICE_BUTTONS: tuple[ProtectButtonEntityDescription, ...] = (
|
ALL_DEVICE_BUTTONS: tuple[ProtectButtonEntityDescription, ...] = (
|
||||||
@ -61,7 +61,7 @@ ALL_DEVICE_BUTTONS: tuple[ProtectButtonEntityDescription, ...] = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
ADOPT_BUTTON = ProtectButtonEntityDescription[ProtectAdoptableDeviceModel](
|
ADOPT_BUTTON = ProtectButtonEntityDescription[ProtectAdoptableDeviceModel](
|
||||||
key=KEY_ADOPT,
|
key="adopt",
|
||||||
name="Adopt device",
|
name="Adopt device",
|
||||||
icon="mdi:plus-circle",
|
icon="mdi:plus-circle",
|
||||||
ufp_press="adopt",
|
ufp_press="adopt",
|
||||||
@ -119,17 +119,25 @@ async def async_setup_entry(
|
|||||||
"""Discover devices on a UniFi Protect NVR."""
|
"""Discover devices on a UniFi Protect NVR."""
|
||||||
data = entry.runtime_data
|
data = entry.runtime_data
|
||||||
|
|
||||||
|
adopt_entities = partial(
|
||||||
|
async_all_device_entities,
|
||||||
|
data,
|
||||||
|
ProtectAdoptButton,
|
||||||
|
unadopted_descs=[ADOPT_BUTTON],
|
||||||
|
)
|
||||||
|
base_entities = partial(
|
||||||
|
async_all_device_entities,
|
||||||
|
data,
|
||||||
|
ProtectButton,
|
||||||
|
all_descs=ALL_DEVICE_BUTTONS,
|
||||||
|
model_descriptions=_MODEL_DESCRIPTIONS,
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _add_new_device(device: ProtectAdoptableDeviceModel) -> None:
|
def _add_new_device(device: ProtectAdoptableDeviceModel) -> None:
|
||||||
entities = async_all_device_entities(
|
async_add_entities(
|
||||||
data,
|
[*base_entities(ufp_device=device), *adopt_entities(ufp_device=device)]
|
||||||
ProtectButton,
|
|
||||||
all_descs=ALL_DEVICE_BUTTONS,
|
|
||||||
unadopted_descs=[ADOPT_BUTTON],
|
|
||||||
model_descriptions=_MODEL_DESCRIPTIONS,
|
|
||||||
ufp_device=device,
|
|
||||||
)
|
)
|
||||||
async_add_entities(entities)
|
|
||||||
_async_remove_adopt_button(hass, device)
|
_async_remove_adopt_button(hass, device)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -137,29 +145,13 @@ async def async_setup_entry(
|
|||||||
if not device.can_adopt or not device.can_create(data.api.bootstrap.auth_user):
|
if not device.can_adopt or not device.can_create(data.api.bootstrap.auth_user):
|
||||||
_LOGGER.debug("Device is not adoptable: %s", device.id)
|
_LOGGER.debug("Device is not adoptable: %s", device.id)
|
||||||
return
|
return
|
||||||
async_add_entities(
|
async_add_entities(adopt_entities(ufp_device=device))
|
||||||
async_all_device_entities(
|
|
||||||
data,
|
|
||||||
ProtectButton,
|
|
||||||
unadopted_descs=[ADOPT_BUTTON],
|
|
||||||
ufp_device=device,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
data.async_subscribe_adopt(_add_new_device)
|
data.async_subscribe_adopt(_add_new_device)
|
||||||
entry.async_on_unload(
|
entry.async_on_unload(
|
||||||
async_dispatcher_connect(hass, data.add_signal, _async_add_unadopted_device)
|
async_dispatcher_connect(hass, data.add_signal, _async_add_unadopted_device)
|
||||||
)
|
)
|
||||||
|
async_add_entities([*base_entities(), *adopt_entities()])
|
||||||
async_add_entities(
|
|
||||||
async_all_device_entities(
|
|
||||||
data,
|
|
||||||
ProtectButton,
|
|
||||||
all_descs=ALL_DEVICE_BUTTONS,
|
|
||||||
unadopted_descs=[ADOPT_BUTTON],
|
|
||||||
model_descriptions=_MODEL_DESCRIPTIONS,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
for device in data.get_by_types(DEVICES_THAT_ADOPT):
|
for device in data.get_by_types(DEVICES_THAT_ADOPT):
|
||||||
_async_remove_adopt_button(hass, device)
|
_async_remove_adopt_button(hass, device)
|
||||||
@ -170,16 +162,20 @@ class ProtectButton(ProtectDeviceEntity, ButtonEntity):
|
|||||||
|
|
||||||
entity_description: ProtectButtonEntityDescription
|
entity_description: ProtectButtonEntityDescription
|
||||||
|
|
||||||
@callback
|
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
|
||||||
super()._async_update_device_from_protect(device)
|
|
||||||
if self.entity_description.key == KEY_ADOPT:
|
|
||||||
device = self.device
|
|
||||||
self._attr_available = device.can_adopt and device.can_create(
|
|
||||||
self.data.api.bootstrap.auth_user
|
|
||||||
)
|
|
||||||
|
|
||||||
async def async_press(self) -> None:
|
async def async_press(self) -> None:
|
||||||
"""Press the button."""
|
"""Press the button."""
|
||||||
if self.entity_description.ufp_press is not None:
|
if self.entity_description.ufp_press is not None:
|
||||||
await getattr(self.device, self.entity_description.ufp_press)()
|
await getattr(self.device, self.entity_description.ufp_press)()
|
||||||
|
|
||||||
|
|
||||||
|
class ProtectAdoptButton(ProtectButton):
|
||||||
|
"""A Ubiquiti UniFi Protect Adopt button."""
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
|
super()._async_update_device_from_protect(device)
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
assert isinstance(device, ProtectAdoptableDeviceModel)
|
||||||
|
self._attr_available = device.can_adopt and device.can_create(
|
||||||
|
self.data.api.bootstrap.auth_user
|
||||||
|
)
|
||||||
|
@ -9,7 +9,6 @@ from uiprotect.data import (
|
|||||||
Camera as UFPCamera,
|
Camera as UFPCamera,
|
||||||
CameraChannel,
|
CameraChannel,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
StateType,
|
StateType,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,7 +27,7 @@ from .const import (
|
|||||||
ATTR_WIDTH,
|
ATTR_WIDTH,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
)
|
)
|
||||||
from .data import ProtectData, UFPConfigEntry
|
from .data import ProtectData, ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity
|
from .entity import ProtectDeviceEntity
|
||||||
from .utils import get_camera_base_name
|
from .utils import get_camera_base_name
|
||||||
|
|
||||||
@ -216,7 +215,7 @@ class ProtectCamera(ProtectDeviceEntity, Camera):
|
|||||||
self._attr_supported_features = _EMPTY_CAMERA_FEATURES
|
self._attr_supported_features = _EMPTY_CAMERA_FEATURES
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
updated_device = self.device
|
updated_device = self.device
|
||||||
channel = updated_device.channels[self.channel.id]
|
channel = updated_device.channels[self.channel.id]
|
||||||
|
@ -9,14 +9,7 @@ import logging
|
|||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from uiprotect.data import (
|
from uiprotect.data import NVR, Event, ModelType, ProtectAdoptableDeviceModel, StateType
|
||||||
NVR,
|
|
||||||
Event,
|
|
||||||
ModelType,
|
|
||||||
ProtectAdoptableDeviceModel,
|
|
||||||
ProtectModelWithId,
|
|
||||||
StateType,
|
|
||||||
)
|
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.helpers.device_registry as dr
|
import homeassistant.helpers.device_registry as dr
|
||||||
@ -30,7 +23,7 @@ from .const import (
|
|||||||
DEFAULT_BRAND,
|
DEFAULT_BRAND,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
)
|
)
|
||||||
from .data import ProtectData
|
from .data import ProtectData, ProtectDeviceType
|
||||||
from .models import PermRequired, ProtectEntityDescription, ProtectEventMixin
|
from .models import PermRequired, ProtectEntityDescription, ProtectEventMixin
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -160,7 +153,7 @@ def async_all_device_entities(
|
|||||||
class BaseProtectEntity(Entity):
|
class BaseProtectEntity(Entity):
|
||||||
"""Base class for UniFi protect entities."""
|
"""Base class for UniFi protect entities."""
|
||||||
|
|
||||||
device: ProtectAdoptableDeviceModel | NVR
|
device: ProtectDeviceType
|
||||||
|
|
||||||
_attr_should_poll = False
|
_attr_should_poll = False
|
||||||
_attr_attribution = DEFAULT_ATTRIBUTION
|
_attr_attribution = DEFAULT_ATTRIBUTION
|
||||||
@ -171,7 +164,7 @@ class BaseProtectEntity(Entity):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
data: ProtectData,
|
data: ProtectData,
|
||||||
device: ProtectAdoptableDeviceModel | NVR,
|
device: ProtectDeviceType,
|
||||||
description: EntityDescription | None = None,
|
description: EntityDescription | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the entity."""
|
"""Initialize the entity."""
|
||||||
@ -203,37 +196,32 @@ class BaseProtectEntity(Entity):
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_set_device_info(self) -> None:
|
def _async_set_device_info(self) -> None:
|
||||||
self._attr_device_info = DeviceInfo(
|
"""Set device info."""
|
||||||
name=self.device.display_name,
|
|
||||||
manufacturer=DEFAULT_BRAND,
|
|
||||||
model=self.device.type,
|
|
||||||
via_device=(DOMAIN, self.data.api.bootstrap.nvr.mac),
|
|
||||||
sw_version=self.device.firmware_version,
|
|
||||||
connections={(dr.CONNECTION_NETWORK_MAC, self.device.mac)},
|
|
||||||
configuration_url=self.device.protect_url,
|
|
||||||
)
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
"""Update Entity object from Protect device."""
|
"""Update Entity object from Protect device."""
|
||||||
if TYPE_CHECKING:
|
was_available = self._attr_available
|
||||||
assert isinstance(device, ProtectAdoptableDeviceModel)
|
if last_updated_success := self.data.last_update_success:
|
||||||
|
|
||||||
if last_update_success := self.data.last_update_success:
|
|
||||||
self.device = device
|
self.device = device
|
||||||
|
|
||||||
async_get_ufp_enabled = self._async_get_ufp_enabled
|
if device.model is ModelType.NVR:
|
||||||
self._attr_available = (
|
available = last_updated_success
|
||||||
last_update_success
|
else:
|
||||||
and (
|
if TYPE_CHECKING:
|
||||||
device.state is StateType.CONNECTED
|
assert isinstance(device, ProtectAdoptableDeviceModel)
|
||||||
or (not device.is_adopted_by_us and device.can_adopt)
|
connected = device.state is StateType.CONNECTED or (
|
||||||
|
not device.is_adopted_by_us and device.can_adopt
|
||||||
)
|
)
|
||||||
and (not async_get_ufp_enabled or async_get_ufp_enabled(device))
|
async_get_ufp_enabled = self._async_get_ufp_enabled
|
||||||
)
|
enabled = not async_get_ufp_enabled or async_get_ufp_enabled(device)
|
||||||
|
available = last_updated_success and connected and enabled
|
||||||
|
|
||||||
|
if available != was_available:
|
||||||
|
self._attr_available = available
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_updated_event(self, device: ProtectAdoptableDeviceModel | NVR) -> None:
|
def _async_updated_event(self, device: ProtectDeviceType) -> None:
|
||||||
"""When device is updated from Protect."""
|
"""When device is updated from Protect."""
|
||||||
previous_attrs = [getter() for getter in self._state_getters]
|
previous_attrs = [getter() for getter in self._state_getters]
|
||||||
self._async_update_device_from_protect(device)
|
self._async_update_device_from_protect(device)
|
||||||
@ -266,10 +254,36 @@ class BaseProtectEntity(Entity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ProtectIsOnEntity(BaseProtectEntity):
|
||||||
|
"""Base class for entities with is_on property."""
|
||||||
|
|
||||||
|
_state_attrs: tuple[str, ...] = ("_attr_available", "_attr_is_on")
|
||||||
|
_attr_is_on: bool | None
|
||||||
|
entity_description: ProtectEntityDescription
|
||||||
|
|
||||||
|
def _async_update_device_from_protect(
|
||||||
|
self, device: ProtectAdoptableDeviceModel | NVR
|
||||||
|
) -> None:
|
||||||
|
super()._async_update_device_from_protect(device)
|
||||||
|
was_on = self._attr_is_on
|
||||||
|
if was_on != (is_on := self.entity_description.get_ufp_value(device) is True):
|
||||||
|
self._attr_is_on = is_on
|
||||||
|
|
||||||
|
|
||||||
class ProtectDeviceEntity(BaseProtectEntity):
|
class ProtectDeviceEntity(BaseProtectEntity):
|
||||||
"""Base class for UniFi protect entities."""
|
"""Base class for UniFi protect entities."""
|
||||||
|
|
||||||
device: ProtectAdoptableDeviceModel
|
@callback
|
||||||
|
def _async_set_device_info(self) -> None:
|
||||||
|
self._attr_device_info = DeviceInfo(
|
||||||
|
name=self.device.display_name,
|
||||||
|
manufacturer=DEFAULT_BRAND,
|
||||||
|
model=self.device.type,
|
||||||
|
via_device=(DOMAIN, self.data.api.bootstrap.nvr.mac),
|
||||||
|
sw_version=self.device.firmware_version,
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, self.device.mac)},
|
||||||
|
configuration_url=self.device.protect_url,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ProtectNVREntity(BaseProtectEntity):
|
class ProtectNVREntity(BaseProtectEntity):
|
||||||
@ -289,14 +303,6 @@ class ProtectNVREntity(BaseProtectEntity):
|
|||||||
configuration_url=self.device.api.base_url,
|
configuration_url=self.device.api.base_url,
|
||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
|
||||||
data = self.data
|
|
||||||
if last_update_success := data.last_update_success:
|
|
||||||
self.device = data.api.bootstrap.nvr
|
|
||||||
|
|
||||||
self._attr_available = last_update_success
|
|
||||||
|
|
||||||
|
|
||||||
class EventEntityMixin(ProtectDeviceEntity):
|
class EventEntityMixin(ProtectDeviceEntity):
|
||||||
"""Adds motion event attributes to sensor."""
|
"""Adds motion event attributes to sensor."""
|
||||||
@ -338,9 +344,8 @@ class EventEntityMixin(ProtectDeviceEntity):
|
|||||||
event object so we need to check the datetime object that was
|
event object so we need to check the datetime object that was
|
||||||
saved from the last time the entity was updated.
|
saved from the last time the entity was updated.
|
||||||
"""
|
"""
|
||||||
event = self._event
|
|
||||||
return bool(
|
return bool(
|
||||||
event
|
(event := self._event)
|
||||||
and event.end
|
and event.end
|
||||||
and prev_event
|
and prev_event
|
||||||
and prev_event_end
|
and prev_event_end
|
||||||
|
@ -4,12 +4,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
|
|
||||||
from uiprotect.data import (
|
from uiprotect.data import Camera, EventType, ProtectAdoptableDeviceModel
|
||||||
Camera,
|
|
||||||
EventType,
|
|
||||||
ProtectAdoptableDeviceModel,
|
|
||||||
ProtectModelWithId,
|
|
||||||
)
|
|
||||||
|
|
||||||
from homeassistant.components.event import (
|
from homeassistant.components.event import (
|
||||||
EventDeviceClass,
|
EventDeviceClass,
|
||||||
@ -20,7 +15,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import ATTR_EVENT_ID
|
from .const import ATTR_EVENT_ID
|
||||||
from .data import ProtectData, UFPConfigEntry
|
from .data import ProtectData, ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import EventEntityMixin, ProtectDeviceEntity
|
from .entity import EventEntityMixin, ProtectDeviceEntity
|
||||||
from .models import ProtectEventMixin
|
from .models import ProtectEventMixin
|
||||||
|
|
||||||
@ -50,7 +45,7 @@ class ProtectDeviceEventEntity(EventEntityMixin, ProtectDeviceEntity, EventEntit
|
|||||||
entity_description: ProtectEventEntityDescription
|
entity_description: ProtectEventEntityDescription
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
description = self.entity_description
|
description = self.entity_description
|
||||||
|
|
||||||
prev_event = self._event
|
prev_event = self._event
|
||||||
|
@ -5,18 +5,13 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from uiprotect.data import (
|
from uiprotect.data import Light, ModelType, ProtectAdoptableDeviceModel
|
||||||
Light,
|
|
||||||
ModelType,
|
|
||||||
ProtectAdoptableDeviceModel,
|
|
||||||
ProtectModelWithId,
|
|
||||||
)
|
|
||||||
|
|
||||||
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .data import UFPConfigEntry
|
from .data import ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity
|
from .entity import ProtectDeviceEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -66,7 +61,7 @@ class ProtectLight(ProtectDeviceEntity, LightEntity):
|
|||||||
_state_attrs = ("_attr_available", "_attr_is_on", "_attr_brightness")
|
_state_attrs = ("_attr_available", "_attr_is_on", "_attr_brightness")
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
updated_device = self.device
|
updated_device = self.device
|
||||||
self._attr_is_on = updated_device.is_light_on
|
self._attr_is_on = updated_device.is_light_on
|
||||||
|
@ -10,14 +10,13 @@ from uiprotect.data import (
|
|||||||
LockStatusType,
|
LockStatusType,
|
||||||
ModelType,
|
ModelType,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.components.lock import LockEntity, LockEntityDescription
|
from homeassistant.components.lock import LockEntity, LockEntityDescription
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .data import UFPConfigEntry
|
from .data import ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity
|
from .entity import ProtectDeviceEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -60,7 +59,7 @@ class ProtectLock(ProtectDeviceEntity, LockEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
lock_status = self.device.lock_status
|
lock_status = self.device.lock_status
|
||||||
|
|
||||||
|
@ -5,12 +5,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from uiprotect.data import (
|
from uiprotect.data import Camera, ProtectAdoptableDeviceModel, StateType
|
||||||
Camera,
|
|
||||||
ProtectAdoptableDeviceModel,
|
|
||||||
ProtectModelWithId,
|
|
||||||
StateType,
|
|
||||||
)
|
|
||||||
from uiprotect.exceptions import StreamError
|
from uiprotect.exceptions import StreamError
|
||||||
|
|
||||||
from homeassistant.components import media_source
|
from homeassistant.components import media_source
|
||||||
@ -28,7 +23,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .data import UFPConfigEntry
|
from .data import ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity
|
from .entity import ProtectDeviceEntity
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -77,7 +72,7 @@ class ProtectMediaPlayer(ProtectDeviceEntity, MediaPlayerEntity):
|
|||||||
_state_attrs = ("_attr_available", "_attr_state", "_attr_volume_level")
|
_state_attrs = ("_attr_available", "_attr_state", "_attr_volume_level")
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
updated_device = self.device
|
updated_device = self.device
|
||||||
self._attr_volume_level = float(updated_device.speaker_settings.volume / 100)
|
self._attr_volume_level = float(updated_device.speaker_settings.volume / 100)
|
||||||
|
@ -12,7 +12,6 @@ from uiprotect.data import (
|
|||||||
Light,
|
Light,
|
||||||
ModelType,
|
ModelType,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.components.number import NumberEntity, NumberEntityDescription
|
from homeassistant.components.number import NumberEntity, NumberEntityDescription
|
||||||
@ -20,7 +19,7 @@ from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfTime
|
|||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .data import ProtectData, UFPConfigEntry
|
from .data import ProtectData, ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity, async_all_device_entities
|
from .entity import ProtectDeviceEntity, async_all_device_entities
|
||||||
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
||||||
|
|
||||||
@ -268,7 +267,7 @@ class ProtectNumbers(ProtectDeviceEntity, NumberEntity):
|
|||||||
self._attr_native_step = self.entity_description.ufp_step
|
self._attr_native_step = self.entity_description.ufp_step
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ from uiprotect.data import (
|
|||||||
ModelType,
|
ModelType,
|
||||||
MountType,
|
MountType,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
RecordingMode,
|
RecordingMode,
|
||||||
Sensor,
|
Sensor,
|
||||||
Viewer,
|
Viewer,
|
||||||
@ -33,7 +32,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import TYPE_EMPTY_VALUE
|
from .const import TYPE_EMPTY_VALUE
|
||||||
from .data import ProtectData, UFPConfigEntry
|
from .data import ProtectData, ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity, async_all_device_entities
|
from .entity import ProtectDeviceEntity, async_all_device_entities
|
||||||
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
||||||
from .utils import async_get_light_motion_current
|
from .utils import async_get_light_motion_current
|
||||||
@ -371,7 +370,7 @@ class ProtectSelects(ProtectDeviceEntity, SelectEntity):
|
|||||||
super().__init__(data, device, description)
|
super().__init__(data, device, description)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
entity_description = self.entity_description
|
entity_description = self.entity_description
|
||||||
# entities with categories are not exposed for voice
|
# entities with categories are not exposed for voice
|
||||||
|
@ -16,7 +16,6 @@ from uiprotect.data import (
|
|||||||
ModelType,
|
ModelType,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectDeviceModel,
|
ProtectDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
Sensor,
|
Sensor,
|
||||||
SmartDetectObjectType,
|
SmartDetectObjectType,
|
||||||
)
|
)
|
||||||
@ -41,7 +40,7 @@ from homeassistant.const import (
|
|||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .data import ProtectData, UFPConfigEntry
|
from .data import ProtectData, ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import (
|
from .entity import (
|
||||||
BaseProtectEntity,
|
BaseProtectEntity,
|
||||||
EventEntityMixin,
|
EventEntityMixin,
|
||||||
@ -721,7 +720,7 @@ class BaseProtectSensor(BaseProtectEntity, SensorEntity):
|
|||||||
entity_description: ProtectSensorEntityDescription
|
entity_description: ProtectSensorEntityDescription
|
||||||
_state_attrs = ("_attr_available", "_attr_native_value")
|
_state_attrs = ("_attr_available", "_attr_native_value")
|
||||||
|
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
||||||
|
|
||||||
@ -756,7 +755,7 @@ class ProtectLicensePlateEventSensor(ProtectEventSensor):
|
|||||||
self._attr_extra_state_attributes = {}
|
self._attr_extra_state_attributes = {}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
description = self.entity_description
|
description = self.entity_description
|
||||||
|
|
||||||
prev_event = self._event
|
prev_event = self._event
|
||||||
|
@ -5,14 +5,12 @@ from __future__ import annotations
|
|||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from functools import partial
|
from functools import partial
|
||||||
import logging
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from uiprotect.data import (
|
from uiprotect.data import (
|
||||||
Camera,
|
Camera,
|
||||||
ModelType,
|
ModelType,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
RecordingMode,
|
RecordingMode,
|
||||||
VideoMode,
|
VideoMode,
|
||||||
)
|
)
|
||||||
@ -23,16 +21,16 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import RestoreEntity
|
||||||
|
|
||||||
from .data import ProtectData, UFPConfigEntry
|
from .data import ProtectData, ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import (
|
from .entity import (
|
||||||
BaseProtectEntity,
|
BaseProtectEntity,
|
||||||
ProtectDeviceEntity,
|
ProtectDeviceEntity,
|
||||||
|
ProtectIsOnEntity,
|
||||||
ProtectNVREntity,
|
ProtectNVREntity,
|
||||||
async_all_device_entities,
|
async_all_device_entities,
|
||||||
)
|
)
|
||||||
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
ATTR_PREV_MIC = "prev_mic_level"
|
ATTR_PREV_MIC = "prev_mic_level"
|
||||||
ATTR_PREV_RECORD = "prev_record_mode"
|
ATTR_PREV_RECORD = "prev_record_mode"
|
||||||
|
|
||||||
@ -45,10 +43,7 @@ class ProtectSwitchEntityDescription(
|
|||||||
|
|
||||||
|
|
||||||
async def _set_highfps(obj: Camera, value: bool) -> None:
|
async def _set_highfps(obj: Camera, value: bool) -> None:
|
||||||
if value:
|
await obj.set_video_mode(VideoMode.HIGH_FPS if value else VideoMode.DEFAULT)
|
||||||
await obj.set_video_mode(VideoMode.HIGH_FPS)
|
|
||||||
else:
|
|
||||||
await obj.set_video_mode(VideoMode.DEFAULT)
|
|
||||||
|
|
||||||
|
|
||||||
CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||||
@ -472,15 +467,10 @@ _PRIVACY_DESCRIPTIONS: dict[ModelType, Sequence[ProtectEntityDescription]] = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ProtectBaseSwitch(BaseProtectEntity, SwitchEntity):
|
class ProtectBaseSwitch(ProtectIsOnEntity):
|
||||||
"""Base class for UniFi Protect Switch."""
|
"""Base class for UniFi Protect Switch."""
|
||||||
|
|
||||||
entity_description: ProtectSwitchEntityDescription
|
entity_description: ProtectSwitchEntityDescription
|
||||||
_state_attrs = ("_attr_available", "_attr_is_on")
|
|
||||||
|
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
|
||||||
super()._async_update_device_from_protect(device)
|
|
||||||
self._attr_is_on = self.entity_description.get_ufp_value(self.device) is True
|
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
@ -491,18 +481,23 @@ class ProtectBaseSwitch(BaseProtectEntity, SwitchEntity):
|
|||||||
await self.entity_description.ufp_set(self.device, False)
|
await self.entity_description.ufp_set(self.device, False)
|
||||||
|
|
||||||
|
|
||||||
class ProtectSwitch(ProtectBaseSwitch, ProtectDeviceEntity):
|
class ProtectSwitch(ProtectDeviceEntity, ProtectBaseSwitch, SwitchEntity):
|
||||||
"""A UniFi Protect Switch."""
|
"""A UniFi Protect Switch."""
|
||||||
|
|
||||||
|
entity_description: ProtectSwitchEntityDescription
|
||||||
|
|
||||||
class ProtectNVRSwitch(ProtectBaseSwitch, ProtectNVREntity):
|
|
||||||
|
class ProtectNVRSwitch(ProtectNVREntity, ProtectBaseSwitch, SwitchEntity):
|
||||||
"""A UniFi Protect NVR Switch."""
|
"""A UniFi Protect NVR Switch."""
|
||||||
|
|
||||||
|
entity_description: ProtectSwitchEntityDescription
|
||||||
|
|
||||||
|
|
||||||
class ProtectPrivacyModeSwitch(RestoreEntity, ProtectSwitch):
|
class ProtectPrivacyModeSwitch(RestoreEntity, ProtectSwitch):
|
||||||
"""A UniFi Protect Switch."""
|
"""A UniFi Protect Switch."""
|
||||||
|
|
||||||
device: Camera
|
device: Camera
|
||||||
|
entity_description: ProtectSwitchEntityDescription
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -533,7 +528,7 @@ class ProtectPrivacyModeSwitch(RestoreEntity, ProtectSwitch):
|
|||||||
self._attr_extra_state_attributes = {}
|
self._attr_extra_state_attributes = {}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
# do not add extra state attribute on initialize
|
# do not add extra state attribute on initialize
|
||||||
if self.entity_id:
|
if self.entity_id:
|
||||||
|
@ -10,7 +10,6 @@ from uiprotect.data import (
|
|||||||
DoorbellMessageType,
|
DoorbellMessageType,
|
||||||
ModelType,
|
ModelType,
|
||||||
ProtectAdoptableDeviceModel,
|
ProtectAdoptableDeviceModel,
|
||||||
ProtectModelWithId,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.components.text import TextEntity, TextEntityDescription
|
from homeassistant.components.text import TextEntity, TextEntityDescription
|
||||||
@ -18,7 +17,7 @@ from homeassistant.const import EntityCategory
|
|||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .data import UFPConfigEntry
|
from .data import ProtectDeviceType, UFPConfigEntry
|
||||||
from .entity import ProtectDeviceEntity, async_all_device_entities
|
from .entity import ProtectDeviceEntity, async_all_device_entities
|
||||||
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
from .models import PermRequired, ProtectEntityDescription, ProtectSetableKeysMixin, T
|
||||||
|
|
||||||
@ -89,7 +88,7 @@ class ProtectDeviceText(ProtectDeviceEntity, TextEntity):
|
|||||||
_state_attrs = ("_attr_available", "_attr_native_value")
|
_state_attrs = ("_attr_available", "_attr_native_value")
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user