Assorted fixes for UniFi Protect (#83032)
This commit is contained in:
parent
e23007322d
commit
6fb9bdec93
7 changed files with 34 additions and 21 deletions
|
@ -30,7 +30,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DEVICE_CLASS_DETECTION, DISPATCH_ADOPT, DOMAIN
|
from .const import DISPATCH_ADOPT, DOMAIN
|
||||||
from .data import ProtectData
|
from .data import ProtectData
|
||||||
from .entity import (
|
from .entity import (
|
||||||
EventEntityMixin,
|
EventEntityMixin,
|
||||||
|
@ -351,7 +351,6 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
key="smart_obj_any",
|
key="smart_obj_any",
|
||||||
name="Object Detected",
|
name="Object Detected",
|
||||||
icon="mdi:eye",
|
icon="mdi:eye",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="feature_flags.has_smart_detect",
|
ufp_required_field="feature_flags.has_smart_detect",
|
||||||
ufp_event_obj="last_smart_detect_event",
|
ufp_event_obj="last_smart_detect_event",
|
||||||
|
@ -360,7 +359,6 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
key="smart_obj_person",
|
key="smart_obj_person",
|
||||||
name="Person Detected",
|
name="Person Detected",
|
||||||
icon="mdi:walk",
|
icon="mdi:walk",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="can_detect_person",
|
ufp_required_field="can_detect_person",
|
||||||
ufp_enabled="is_person_detection_on",
|
ufp_enabled="is_person_detection_on",
|
||||||
|
@ -371,7 +369,6 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
key="smart_obj_vehicle",
|
key="smart_obj_vehicle",
|
||||||
name="Vehicle Detected",
|
name="Vehicle Detected",
|
||||||
icon="mdi:car",
|
icon="mdi:car",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="can_detect_vehicle",
|
ufp_required_field="can_detect_vehicle",
|
||||||
ufp_enabled="is_vehicle_detection_on",
|
ufp_enabled="is_vehicle_detection_on",
|
||||||
|
@ -381,7 +378,6 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
ProtectBinaryEventEntityDescription(
|
ProtectBinaryEventEntityDescription(
|
||||||
key="smart_obj_face",
|
key="smart_obj_face",
|
||||||
name="Face Detected",
|
name="Face Detected",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
icon="mdi:mdi-face",
|
icon="mdi:mdi-face",
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="can_detect_face",
|
ufp_required_field="can_detect_face",
|
||||||
|
@ -392,7 +388,6 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
ProtectBinaryEventEntityDescription(
|
ProtectBinaryEventEntityDescription(
|
||||||
key="smart_obj_package",
|
key="smart_obj_package",
|
||||||
name="Package Detected",
|
name="Package Detected",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
icon="mdi:package-variant-closed",
|
icon="mdi:package-variant-closed",
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="can_detect_package",
|
ufp_required_field="can_detect_package",
|
||||||
|
@ -402,9 +397,8 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
),
|
),
|
||||||
ProtectBinaryEventEntityDescription(
|
ProtectBinaryEventEntityDescription(
|
||||||
key="smart_audio_any",
|
key="smart_audio_any",
|
||||||
name="Audio Detected",
|
name="Audio Object Detected",
|
||||||
icon="mdi:eye",
|
icon="mdi:eye",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="feature_flags.has_smart_detect",
|
ufp_required_field="feature_flags.has_smart_detect",
|
||||||
ufp_event_obj="last_smart_audio_detect_event",
|
ufp_event_obj="last_smart_audio_detect_event",
|
||||||
|
@ -412,7 +406,6 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
ProtectBinaryEventEntityDescription(
|
ProtectBinaryEventEntityDescription(
|
||||||
key="smart_audio_smoke",
|
key="smart_audio_smoke",
|
||||||
name="Smoke Alarm Detected",
|
name="Smoke Alarm Detected",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
icon="mdi:fire",
|
icon="mdi:fire",
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="can_detect_smoke",
|
ufp_required_field="can_detect_smoke",
|
||||||
|
@ -423,7 +416,6 @@ MOTION_SENSORS: tuple[ProtectBinaryEventEntityDescription, ...] = (
|
||||||
ProtectBinaryEventEntityDescription(
|
ProtectBinaryEventEntityDescription(
|
||||||
key="smart_audio_cmonx",
|
key="smart_audio_cmonx",
|
||||||
name="CO Alarm Detected",
|
name="CO Alarm Detected",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
|
||||||
icon="mdi:fire",
|
icon="mdi:fire",
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
ufp_required_field="can_detect_smoke",
|
ufp_required_field="can_detect_smoke",
|
||||||
|
@ -629,4 +621,8 @@ class ProtectEventBinarySensor(EventEntityMixin, BinarySensorEntity):
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
self._attr_is_on = self.entity_description.get_ufp_value(self.device)
|
is_on = self.entity_description.get_is_on(device)
|
||||||
|
self._attr_is_on: bool | None = is_on
|
||||||
|
if not is_on:
|
||||||
|
self._event = None
|
||||||
|
self._attr_extra_state_attributes = {}
|
||||||
|
|
|
@ -68,5 +68,3 @@ PLATFORMS = [
|
||||||
DISPATCH_ADD = "add_device"
|
DISPATCH_ADD = "add_device"
|
||||||
DISPATCH_ADOPT = "adopt_device"
|
DISPATCH_ADOPT = "adopt_device"
|
||||||
DISPATCH_CHANNELS = "new_camera_channels"
|
DISPATCH_CHANNELS = "new_camera_channels"
|
||||||
|
|
||||||
DEVICE_CLASS_DETECTION = "unifiprotect__detection"
|
|
||||||
|
|
|
@ -325,7 +325,6 @@ class EventEntityMixin(ProtectDeviceEntity):
|
||||||
@callback
|
@callback
|
||||||
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
def _async_update_device_from_protect(self, device: ProtectModelWithId) -> None:
|
||||||
super()._async_update_device_from_protect(device)
|
super()._async_update_device_from_protect(device)
|
||||||
self._attr_is_on: bool | None = self.entity_description.get_is_on(device)
|
|
||||||
self._event = self.entity_description.get_event_obj(device)
|
self._event = self.entity_description.get_event_obj(device)
|
||||||
|
|
||||||
attrs = self.extra_state_attributes or {}
|
attrs = self.extra_state_attributes or {}
|
||||||
|
|
|
@ -41,7 +41,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity import EntityCategory
|
from homeassistant.helpers.entity import EntityCategory
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import DEVICE_CLASS_DETECTION, DISPATCH_ADOPT, DOMAIN
|
from .const import DISPATCH_ADOPT, DOMAIN
|
||||||
from .data import ProtectData
|
from .data import ProtectData
|
||||||
from .entity import (
|
from .entity import (
|
||||||
EventEntityMixin,
|
EventEntityMixin,
|
||||||
|
@ -54,6 +54,8 @@ from .utils import async_dispatch_id as _ufpd, async_get_light_motion_current
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
OBJECT_TYPE_NONE = "none"
|
OBJECT_TYPE_NONE = "none"
|
||||||
|
DEVICE_CLASS_DETECTION = "unifiprotect__detection"
|
||||||
|
DEVICE_CLASS_LICENSE_PLATE = "unifiprotect__license_plate"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
@ -532,8 +534,9 @@ MOTION_SENSORS: tuple[ProtectSensorEventEntityDescription, ...] = (
|
||||||
key="smart_obj_licenseplate",
|
key="smart_obj_licenseplate",
|
||||||
name="License Plate Detected",
|
name="License Plate Detected",
|
||||||
icon="mdi:car",
|
icon="mdi:car",
|
||||||
device_class=DEVICE_CLASS_DETECTION,
|
device_class=DEVICE_CLASS_LICENSE_PLATE,
|
||||||
ufp_value="is_smart_detected",
|
ufp_value="is_smart_detected",
|
||||||
|
ufp_required_field="can_detect_license_plate",
|
||||||
ufp_event_obj="last_smart_detect_event",
|
ufp_event_obj="last_smart_detect_event",
|
||||||
ufp_smart_type=SmartDetectObjectType.LICENSE_PLATE,
|
ufp_smart_type=SmartDetectObjectType.LICENSE_PLATE,
|
||||||
),
|
),
|
||||||
|
@ -685,6 +688,9 @@ def _async_motion_entities(
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for event_desc in MOTION_SENSORS:
|
for event_desc in MOTION_SENSORS:
|
||||||
|
if not event_desc.has_required(device):
|
||||||
|
continue
|
||||||
|
|
||||||
entities.append(ProtectEventSensor(data, device, event_desc))
|
entities.append(ProtectEventSensor(data, device, event_desc))
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Adding sensor entity %s for %s",
|
"Adding sensor entity %s for %s",
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"state": {
|
||||||
|
"unifiprotect__license_plate": {
|
||||||
|
"none": "Clear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"state": {
|
||||||
|
"unifiprotect__license_plate": {
|
||||||
|
"none": "Clear"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,11 +62,11 @@ async def test_sensor_camera_remove(
|
||||||
|
|
||||||
ufp.api.bootstrap.nvr.system_info.ustorage = None
|
ufp.api.bootstrap.nvr.system_info.ustorage = None
|
||||||
await init_entry(hass, ufp, [doorbell, unadopted_camera])
|
await init_entry(hass, ufp, [doorbell, unadopted_camera])
|
||||||
assert_entity_counts(hass, Platform.SENSOR, 26, 13)
|
assert_entity_counts(hass, Platform.SENSOR, 25, 12)
|
||||||
await remove_entities(hass, ufp, [doorbell, unadopted_camera])
|
await remove_entities(hass, ufp, [doorbell, unadopted_camera])
|
||||||
assert_entity_counts(hass, Platform.SENSOR, 12, 9)
|
assert_entity_counts(hass, Platform.SENSOR, 12, 9)
|
||||||
await adopt_devices(hass, ufp, [doorbell, unadopted_camera])
|
await adopt_devices(hass, ufp, [doorbell, unadopted_camera])
|
||||||
assert_entity_counts(hass, Platform.SENSOR, 26, 13)
|
assert_entity_counts(hass, Platform.SENSOR, 25, 12)
|
||||||
|
|
||||||
|
|
||||||
async def test_sensor_sensor_remove(
|
async def test_sensor_sensor_remove(
|
||||||
|
@ -318,7 +318,7 @@ async def test_sensor_setup_camera(
|
||||||
"""Test sensor entity setup for camera devices."""
|
"""Test sensor entity setup for camera devices."""
|
||||||
|
|
||||||
await init_entry(hass, ufp, [doorbell])
|
await init_entry(hass, ufp, [doorbell])
|
||||||
assert_entity_counts(hass, Platform.SENSOR, 26, 13)
|
assert_entity_counts(hass, Platform.SENSOR, 25, 12)
|
||||||
|
|
||||||
entity_registry = er.async_get(hass)
|
entity_registry = er.async_get(hass)
|
||||||
|
|
||||||
|
@ -424,7 +424,7 @@ async def test_sensor_setup_camera_with_last_trip_time(
|
||||||
"""Test sensor entity setup for camera devices with last trip time."""
|
"""Test sensor entity setup for camera devices with last trip time."""
|
||||||
|
|
||||||
await init_entry(hass, ufp, [doorbell])
|
await init_entry(hass, ufp, [doorbell])
|
||||||
assert_entity_counts(hass, Platform.SENSOR, 26, 26)
|
assert_entity_counts(hass, Platform.SENSOR, 25, 25)
|
||||||
|
|
||||||
entity_registry = er.async_get(hass)
|
entity_registry = er.async_get(hass)
|
||||||
|
|
||||||
|
@ -452,7 +452,7 @@ async def test_sensor_update_motion(
|
||||||
"""Test sensor motion entity."""
|
"""Test sensor motion entity."""
|
||||||
|
|
||||||
await init_entry(hass, ufp, [doorbell])
|
await init_entry(hass, ufp, [doorbell])
|
||||||
assert_entity_counts(hass, Platform.SENSOR, 26, 13)
|
assert_entity_counts(hass, Platform.SENSOR, 25, 12)
|
||||||
|
|
||||||
_, entity_id = ids_from_device_description(
|
_, entity_id = ids_from_device_description(
|
||||||
Platform.SENSOR, doorbell, MOTION_SENSORS[0]
|
Platform.SENSOR, doorbell, MOTION_SENSORS[0]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue