mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Reduce code needed to check unifiprotect attrs (#119706)
* Reduce code needed to check unifiprotect attrs * Apply suggestions from code review * Update homeassistant/components/unifiprotect/manifest.json * Apply suggestions from code review * revert * adjust * tweak * make mypy happy
This commit is contained in:
parent
f8bf357811
commit
c0ff2d866f
@ -5,7 +5,6 @@ from __future__ import annotations
|
||||
from collections.abc import Sequence
|
||||
import dataclasses
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from uiprotect.data import (
|
||||
NVR,
|
||||
@ -632,26 +631,23 @@ class ProtectDeviceBinarySensor(ProtectDeviceEntity, BinarySensorEntity):
|
||||
|
||||
device: Camera | Light | Sensor
|
||||
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)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
return (self._attr_available, self._attr_is_on)
|
||||
|
||||
|
||||
class MountableProtectDeviceBinarySensor(ProtectDeviceBinarySensor):
|
||||
"""A UniFi Protect Device Binary Sensor that can change device class at runtime."""
|
||||
|
||||
device: Sensor
|
||||
_state_attrs: tuple[str, ...] = (
|
||||
"_attr_available",
|
||||
"_attr_is_on",
|
||||
"_attr_device_class",
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||
@ -662,21 +658,13 @@ class MountableProtectDeviceBinarySensor(ProtectDeviceBinarySensor):
|
||||
updated_device.mount_type, BinarySensorDeviceClass.DOOR
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
return (self._attr_available, self._attr_is_on, self._attr_device_class)
|
||||
|
||||
|
||||
class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity):
|
||||
"""A UniFi Protect NVR Disk Binary Sensor."""
|
||||
|
||||
_disk: UOSDisk
|
||||
entity_description: ProtectBinaryEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_is_on")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -715,21 +703,12 @@ class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity):
|
||||
|
||||
self._attr_is_on = not self._disk.is_healthy
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_is_on)
|
||||
|
||||
|
||||
class ProtectEventBinarySensor(EventEntityMixin, BinarySensorEntity):
|
||||
"""A UniFi Protect Device Binary Sensor for events."""
|
||||
|
||||
entity_description: ProtectBinaryEventEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_is_on", "_attr_extra_state_attributes")
|
||||
|
||||
@callback
|
||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||
@ -740,20 +719,6 @@ class ProtectEventBinarySensor(EventEntityMixin, BinarySensorEntity):
|
||||
self._event = None
|
||||
self._attr_extra_state_attributes = {}
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (
|
||||
self._attr_available,
|
||||
self._attr_is_on,
|
||||
self._attr_extra_state_attributes,
|
||||
)
|
||||
|
||||
|
||||
MODEL_DESCRIPTIONS_WITH_CLASS = (
|
||||
(_MODEL_DESCRIPTIONS, ProtectDeviceBinarySensor),
|
||||
|
@ -186,7 +186,6 @@ class ProtectButton(ProtectDeviceEntity, ButtonEntity):
|
||||
@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(
|
||||
@ -195,6 +194,5 @@ class ProtectButton(ProtectDeviceEntity, ButtonEntity):
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Press the button."""
|
||||
|
||||
if self.entity_description.ufp_press is not None:
|
||||
await getattr(self.device, self.entity_description.ufp_press)()
|
||||
|
@ -3,7 +3,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from typing_extensions import Generator
|
||||
from uiprotect.data import (
|
||||
@ -163,6 +162,11 @@ class ProtectCamera(ProtectDeviceEntity, Camera):
|
||||
"""A Ubiquiti UniFi Protect Camera."""
|
||||
|
||||
device: UFPCamera
|
||||
_state_attrs = (
|
||||
"_attr_available",
|
||||
"_attr_is_recording",
|
||||
"_attr_motion_detection_enabled",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -210,20 +214,6 @@ class ProtectCamera(ProtectDeviceEntity, Camera):
|
||||
else:
|
||||
self._attr_supported_features = CameraEntityFeature(0)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (
|
||||
self._attr_available,
|
||||
self._attr_is_recording,
|
||||
self._attr_motion_detection_enabled,
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||
super()._async_update_device_from_protect(device)
|
||||
|
@ -3,7 +3,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Sequence
|
||||
from functools import partial
|
||||
import logging
|
||||
from operator import attrgetter
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from uiprotect.data import (
|
||||
@ -161,6 +163,7 @@ class BaseProtectEntity(Entity):
|
||||
device: ProtectAdoptableDeviceModel | NVR
|
||||
|
||||
_attr_should_poll = False
|
||||
_state_attrs: tuple[str, ...] = ("_attr_available",)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -194,6 +197,9 @@ class BaseProtectEntity(Entity):
|
||||
self._attr_attribution = DEFAULT_ATTRIBUTION
|
||||
self._async_set_device_info()
|
||||
self._async_update_device_from_protect(device)
|
||||
self._state_getters = tuple(
|
||||
partial(attrgetter(attr), self) for attr in self._state_attrs
|
||||
)
|
||||
|
||||
async def async_update(self) -> None:
|
||||
"""Update the entity.
|
||||
@ -233,24 +239,18 @@ class BaseProtectEntity(Entity):
|
||||
and (not async_get_ufp_enabled or async_get_ufp_enabled(device))
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available,)
|
||||
|
||||
@callback
|
||||
def _async_updated_event(self, device: ProtectAdoptableDeviceModel | NVR) -> None:
|
||||
"""When device is updated from Protect."""
|
||||
|
||||
previous_attrs = self._async_get_state_attrs()
|
||||
previous_attrs = [getter() for getter in self._state_getters]
|
||||
self._async_update_device_from_protect(device)
|
||||
current_attrs = self._async_get_state_attrs()
|
||||
if previous_attrs != current_attrs:
|
||||
changed = False
|
||||
for idx, getter in enumerate(self._state_getters):
|
||||
if previous_attrs[idx] != getter():
|
||||
changed = True
|
||||
break
|
||||
|
||||
if changed:
|
||||
if _LOGGER.isEnabledFor(logging.DEBUG):
|
||||
device_name = device.name or ""
|
||||
if hasattr(self, "entity_description") and self.entity_description.name:
|
||||
@ -261,7 +261,7 @@ class BaseProtectEntity(Entity):
|
||||
device_name,
|
||||
device.mac,
|
||||
previous_attrs,
|
||||
current_attrs,
|
||||
tuple((getattr(self, attr)) for attr in self._state_attrs),
|
||||
)
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -63,16 +63,7 @@ class ProtectLight(ProtectDeviceEntity, LightEntity):
|
||||
_attr_icon = "mdi:spotlight-beam"
|
||||
_attr_color_mode = ColorMode.BRIGHTNESS
|
||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_is_on, self._attr_brightness)
|
||||
_state_attrs = ("_attr_available", "_attr_is_on", "_attr_brightness")
|
||||
|
||||
@callback
|
||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||
|
@ -49,6 +49,13 @@ class ProtectLock(ProtectDeviceEntity, LockEntity):
|
||||
|
||||
device: Doorlock
|
||||
entity_description: LockEntityDescription
|
||||
_state_attrs = (
|
||||
"_attr_available",
|
||||
"_attr_is_locked",
|
||||
"_attr_is_locking",
|
||||
"_attr_is_unlocking",
|
||||
"_attr_is_jammed",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -64,22 +71,6 @@ class ProtectLock(ProtectDeviceEntity, LockEntity):
|
||||
|
||||
self._attr_name = f"{self.device.display_name} Lock"
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (
|
||||
self._attr_available,
|
||||
self._attr_is_locked,
|
||||
self._attr_is_locking,
|
||||
self._attr_is_unlocking,
|
||||
self._attr_is_jammed,
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||
super()._async_update_device_from_protect(device)
|
||||
|
@ -69,6 +69,7 @@ class ProtectMediaPlayer(ProtectDeviceEntity, MediaPlayerEntity):
|
||||
| MediaPlayerEntityFeature.STOP
|
||||
| MediaPlayerEntityFeature.BROWSE_MEDIA
|
||||
)
|
||||
_state_attrs = ("_attr_available", "_attr_state", "_attr_volume_level")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -107,16 +108,6 @@ class ProtectMediaPlayer(ProtectDeviceEntity, MediaPlayerEntity):
|
||||
)
|
||||
self._attr_available = is_connected and updated_device.feature_flags.has_speaker
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_state, self._attr_volume_level)
|
||||
|
||||
async def async_set_volume_level(self, volume: float) -> None:
|
||||
"""Set volume level, range 0..1."""
|
||||
|
||||
|
@ -6,7 +6,6 @@ from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from uiprotect.data import (
|
||||
Camera,
|
||||
@ -257,6 +256,7 @@ class ProtectNumbers(ProtectDeviceEntity, NumberEntity):
|
||||
|
||||
device: Camera | Light
|
||||
entity_description: ProtectNumberEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_native_value")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -278,13 +278,3 @@ class ProtectNumbers(ProtectDeviceEntity, NumberEntity):
|
||||
async def async_set_native_value(self, value: float) -> None:
|
||||
"""Set new value."""
|
||||
await self.entity_description.ufp_set(self.device, value)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_native_value)
|
||||
|
@ -358,6 +358,7 @@ class ProtectSelects(ProtectDeviceEntity, SelectEntity):
|
||||
|
||||
device: Camera | Light | Viewer
|
||||
entity_description: ProtectSelectEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_options", "_attr_current_option")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -418,13 +419,3 @@ class ProtectSelects(ProtectDeviceEntity, SelectEntity):
|
||||
if self.entity_description.ufp_enum_type is not None:
|
||||
unifi_value = self.entity_description.ufp_enum_type(unifi_value)
|
||||
await self.entity_description.ufp_set(self.device, unifi_value)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_options, self._attr_current_option)
|
||||
|
@ -702,60 +702,33 @@ class ProtectDeviceSensor(ProtectDeviceEntity, SensorEntity):
|
||||
"""A Ubiquiti UniFi Protect Sensor."""
|
||||
|
||||
entity_description: ProtectSensorEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_native_value")
|
||||
|
||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||
super()._async_update_device_from_protect(device)
|
||||
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_native_value)
|
||||
|
||||
|
||||
class ProtectNVRSensor(ProtectNVREntity, SensorEntity):
|
||||
"""A Ubiquiti UniFi Protect Sensor."""
|
||||
|
||||
entity_description: ProtectSensorEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_native_value")
|
||||
|
||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||
super()._async_update_device_from_protect(device)
|
||||
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_native_value)
|
||||
|
||||
|
||||
class ProtectEventSensor(EventEntityMixin, SensorEntity):
|
||||
"""A UniFi Protect Device Sensor with access tokens."""
|
||||
|
||||
entity_description: ProtectSensorEventEntityDescription
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (
|
||||
self._attr_available,
|
||||
self._attr_native_value,
|
||||
self._attr_extra_state_attributes,
|
||||
)
|
||||
_state_attrs = (
|
||||
"_attr_available",
|
||||
"_attr_native_value",
|
||||
"_attr_extra_state_attributes",
|
||||
)
|
||||
|
||||
|
||||
class ProtectLicensePlateEventSensor(ProtectEventSensor):
|
||||
|
@ -476,6 +476,7 @@ class ProtectSwitch(ProtectDeviceEntity, SwitchEntity):
|
||||
"""A UniFi Protect Switch."""
|
||||
|
||||
entity_description: ProtectSwitchEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_is_on")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -500,20 +501,12 @@ class ProtectSwitch(ProtectDeviceEntity, SwitchEntity):
|
||||
"""Turn the device off."""
|
||||
await self.entity_description.ufp_set(self.device, False)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
return (self._attr_available, self._attr_is_on)
|
||||
|
||||
|
||||
class ProtectNVRSwitch(ProtectNVREntity, SwitchEntity):
|
||||
"""A UniFi Protect NVR Switch."""
|
||||
|
||||
entity_description: ProtectSwitchEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_is_on")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -537,15 +530,6 @@ class ProtectNVRSwitch(ProtectNVREntity, SwitchEntity):
|
||||
"""Turn the device off."""
|
||||
await self.entity_description.ufp_set(self.device, False)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
return (self._attr_available, self._attr_is_on)
|
||||
|
||||
|
||||
class ProtectPrivacyModeSwitch(RestoreEntity, ProtectSwitch):
|
||||
"""A UniFi Protect Switch."""
|
||||
|
@ -4,7 +4,6 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from uiprotect.data import (
|
||||
Camera,
|
||||
@ -87,6 +86,7 @@ class ProtectDeviceText(ProtectDeviceEntity, TextEntity):
|
||||
"""A Ubiquiti UniFi Protect Sensor."""
|
||||
|
||||
entity_description: ProtectTextEntityDescription
|
||||
_state_attrs = ("_attr_available", "_attr_native_value")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -102,17 +102,6 @@ class ProtectDeviceText(ProtectDeviceEntity, TextEntity):
|
||||
super()._async_update_device_from_protect(device)
|
||||
self._attr_native_value = self.entity_description.get_ufp_value(self.device)
|
||||
|
||||
@callback
|
||||
def _async_get_state_attrs(self) -> tuple[Any, ...]:
|
||||
"""Retrieve data that goes into the current state of the entity.
|
||||
|
||||
Called before and after updating entity and state is only written if there
|
||||
is a change.
|
||||
"""
|
||||
|
||||
return (self._attr_available, self._attr_native_value)
|
||||
|
||||
async def async_set_value(self, value: str) -> None:
|
||||
"""Change the value."""
|
||||
|
||||
await self.entity_description.ufp_set(self.device, value)
|
||||
|
Loading…
x
Reference in New Issue
Block a user