1
mirror of https://github.com/home-assistant/core synced 2024-07-18 12:02:20 +02:00

Add sensors for read-only devices for UniFi Protect (#73768)

This commit is contained in:
Christopher Bailey 2022-06-21 13:01:06 -04:00 committed by GitHub
parent db9c242723
commit 9940a85e28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 391 additions and 31 deletions

View File

@ -34,7 +34,8 @@ from .entity import (
ProtectNVREntity,
async_all_device_entities,
)
from .models import ProtectRequiredKeysMixin
from .models import PermRequired, ProtectRequiredKeysMixin
from .utils import async_get_is_highfps
_LOGGER = logging.getLogger(__name__)
_KEY_DOOR = "door"
@ -69,6 +70,126 @@ CAMERA_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
icon="mdi:brightness-6",
ufp_value="is_dark",
),
ProtectBinaryEntityDescription(
key="ssh",
name="SSH Enabled",
icon="mdi:lock",
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="is_ssh_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="feature_flags.has_led_status",
ufp_value="led_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="hdr_mode",
name="HDR Mode",
icon="mdi:brightness-7",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="feature_flags.has_hdr",
ufp_value="hdr_mode",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="high_fps",
name="High FPS",
icon="mdi:video-high-definition",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="feature_flags.has_highfps",
ufp_value_fn=async_get_is_highfps,
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="system_sounds",
name="System Sounds",
icon="mdi:speaker",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="feature_flags.has_speaker",
ufp_value="speaker_settings.are_system_sounds_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="osd_name",
name="Overlay: Show Name",
icon="mdi:fullscreen",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="osd_settings.is_name_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="osd_date",
name="Overlay: Show Date",
icon="mdi:fullscreen",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="osd_settings.is_date_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="osd_logo",
name="Overlay: Show Logo",
icon="mdi:fullscreen",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="osd_settings.is_logo_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="osd_bitrate",
name="Overlay: Show Bitrate",
icon="mdi:fullscreen",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="osd_settings.is_debug_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="motion",
name="Detections: Motion",
icon="mdi:run-fast",
ufp_value="recording_settings.enable_motion_detection",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="smart_person",
name="Detections: Person",
icon="mdi:walk",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="can_detect_person",
ufp_value="is_person_detection_on",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="smart_vehicle",
name="Detections: Vehicle",
icon="mdi:car",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="can_detect_vehicle",
ufp_value="is_vehicle_detection_on",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="smart_face",
name="Detections: Face",
icon="mdi:human-greeting",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="can_detect_face",
ufp_value="is_face_detection_on",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="smart_package",
name="Detections: Package",
icon="mdi:package-variant-closed",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="can_detect_package",
ufp_value="is_package_detection_on",
ufp_perm=PermRequired.NO_WRITE,
),
)
LIGHT_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
@ -84,6 +205,31 @@ LIGHT_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
device_class=BinarySensorDeviceClass.MOTION,
ufp_value="is_pir_motion_detected",
),
ProtectBinaryEntityDescription(
key="light",
name="Flood Light",
icon="mdi:spotlight-beam",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="is_light_on",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="ssh",
name="SSH Enabled",
icon="mdi:lock",
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="is_ssh_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="light_device_settings.is_indicator_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
)
SENSE_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
@ -114,6 +260,53 @@ SENSE_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
device_class=BinarySensorDeviceClass.TAMPER,
ufp_value="is_tampering_detected",
),
ProtectBinaryEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="led_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="motion",
name="Motion Detection",
icon="mdi:walk",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="motion_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="temperature",
name="Temperature Sensor",
icon="mdi:thermometer",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="temperature_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="humidity",
name="Humidity Sensor",
icon="mdi:water-percent",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="humidity_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="light",
name="Light Sensor",
icon="mdi:brightness-5",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="light_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectBinaryEntityDescription(
key="alarm",
name="Alarm Sound Detection",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="alarm_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
)
MOTION_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
@ -133,6 +326,26 @@ DOORLOCK_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="battery_status.is_low",
),
ProtectBinaryEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="led_settings.is_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
)
VIEWER_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
ProtectBinaryEntityDescription(
key="ssh",
name="SSH Enabled",
icon="mdi:lock",
entity_registry_enabled_default=False,
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="is_ssh_enabled",
ufp_perm=PermRequired.NO_WRITE,
),
)
@ -159,6 +372,7 @@ async def async_setup_entry(
light_descs=LIGHT_SENSORS,
sense_descs=SENSE_SENSORS,
lock_descs=DOORLOCK_SENSORS,
viewer_descs=VIEWER_SENSORS,
)
entities += _async_motion_entities(data)
entities += _async_nvr_entities(data)

View File

@ -50,6 +50,8 @@ def _async_device_entities(
can_write = device.can_write(data.api.bootstrap.auth_user)
if description.ufp_perm == PermRequired.WRITE and not can_write:
continue
if description.ufp_perm == PermRequired.NO_WRITE and can_write:
continue
if description.ufp_required_field:
required_field = get_nested_attr(device, description.ufp_required_field)

View File

@ -39,6 +39,7 @@ from .const import ATTR_DURATION, ATTR_MESSAGE, DOMAIN, TYPE_EMPTY_VALUE
from .data import ProtectData
from .entity import ProtectDeviceEntity, async_all_device_entities
from .models import PermRequired, ProtectSetableKeysMixin, T
from .utils import async_get_light_motion_current
_LOGGER = logging.getLogger(__name__)
_KEY_LIGHT_MOTION = "light_motion"
@ -151,16 +152,6 @@ def _get_viewer_current(obj: Viewer) -> str:
return obj.liveview_id
def _get_light_motion_current(obj: Light) -> str:
# a bit of extra to allow On Motion Always/Dark
if (
obj.light_mode_settings.mode == LightModeType.MOTION
and obj.light_mode_settings.enable_at == LightModeEnableType.DARK
):
return f"{LightModeType.MOTION.value}Dark"
return obj.light_mode_settings.mode.value
def _get_doorbell_current(obj: Camera) -> str | None:
if obj.lcd_message is None:
return None
@ -255,7 +246,7 @@ LIGHT_SELECTS: tuple[ProtectSelectEntityDescription, ...] = (
icon="mdi:spotlight",
entity_category=EntityCategory.CONFIG,
ufp_options=MOTION_MODE_TO_LIGHT_MODE,
ufp_value_fn=_get_light_motion_current,
ufp_value_fn=async_get_light_motion_current,
ufp_set_method_fn=_set_light_mode,
ufp_perm=PermRequired.WRITE,
),

View File

@ -10,6 +10,7 @@ from pyunifiprotect.data import (
NVR,
Camera,
Event,
Light,
ProtectAdoptableDeviceModel,
ProtectDeviceModel,
ProtectModelWithId,
@ -46,7 +47,8 @@ from .entity import (
ProtectNVREntity,
async_all_device_entities,
)
from .models import ProtectRequiredKeysMixin, T
from .models import PermRequired, ProtectRequiredKeysMixin, T
from .utils import async_get_light_motion_current
_LOGGER = logging.getLogger(__name__)
OBJECT_TYPE_NONE = "none"
@ -197,6 +199,51 @@ CAMERA_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
ufp_value="last_ring",
entity_registry_enabled_default=False,
),
ProtectSensorEntityDescription(
key="mic_level",
name="Microphone Level",
icon="mdi:microphone",
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="feature_flags.has_mic",
ufp_value="mic_volume",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription(
key="recording_mode",
name="Recording Mode",
icon="mdi:video-outline",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="recording_settings.mode",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription(
key="infrared",
name="Infrared Mode",
icon="mdi:circle-opacity",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="feature_flags.has_led_ir",
ufp_value="isp_settings.ir_led_mode",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription(
key="doorbell_text",
name="Doorbell Text",
icon="mdi:card-text",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_required_field="feature_flags.has_lcd_screen",
ufp_value="lcd_message.text",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription(
key="chime_type",
name="Chime Type",
icon="mdi:bell",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
ufp_required_field="feature_flags.has_chime",
ufp_value="chime_type",
),
)
CAMERA_DISABLED_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
@ -284,6 +331,31 @@ SENSE_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
ufp_value="tampering_detected_at",
entity_registry_enabled_default=False,
),
ProtectSensorEntityDescription(
key="sensitivity",
name="Motion Sensitivity",
icon="mdi:walk",
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="motion_settings.sensitivity",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription(
key="mount_type",
name="Mount Type",
icon="mdi:screwdriver",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="mount_type",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription(
key="paired_camera",
name="Paired Camera",
icon="mdi:cctv",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="camera.name",
ufp_perm=PermRequired.NO_WRITE,
),
)
DOORLOCK_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
@ -296,6 +368,14 @@ DOORLOCK_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
ufp_value="battery_status.percentage",
),
ProtectSensorEntityDescription(
key="paired_camera",
name="Paired Camera",
icon="mdi:cctv",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="camera.name",
ufp_perm=PermRequired.NO_WRITE,
),
)
NVR_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
@ -439,6 +519,31 @@ LIGHT_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
ufp_value="last_motion",
entity_registry_enabled_default=False,
),
ProtectSensorEntityDescription(
key="sensitivity",
name="Motion Sensitivity",
icon="mdi:walk",
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="light_device_settings.pir_sensitivity",
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription[Light](
key="light_motion",
name="Light Mode",
icon="mdi:spotlight",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value_fn=async_get_light_motion_current,
ufp_perm=PermRequired.NO_WRITE,
),
ProtectSensorEntityDescription(
key="paired_camera",
name="Paired Camera",
icon="mdi:cctv",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="camera.name",
ufp_perm=PermRequired.NO_WRITE,
),
)
MOTION_TRIP_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
@ -459,6 +564,26 @@ CHIME_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
icon="mdi:bell",
ufp_value="last_ring",
),
ProtectSensorEntityDescription(
key="volume",
name="Volume",
icon="mdi:speaker",
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="volume",
ufp_perm=PermRequired.NO_WRITE,
),
)
VIEWER_SENSORS: tuple[ProtectSensorEntityDescription, ...] = (
ProtectSensorEntityDescription(
key="viewer",
name="Liveview",
icon="mdi:view-dashboard",
entity_category=EntityCategory.DIAGNOSTIC,
ufp_value="liveview.name",
ufp_perm=PermRequired.NO_WRITE,
),
)
@ -478,6 +603,7 @@ async def async_setup_entry(
light_descs=LIGHT_SENSORS,
lock_descs=DOORLOCK_SENSORS,
chime_descs=CHIME_SENSORS,
viewer_descs=VIEWER_SENSORS,
)
entities += _async_motion_entities(data)
entities += _async_nvr_entities(data)

View File

@ -22,6 +22,7 @@ from .const import DOMAIN
from .data import ProtectData
from .entity import ProtectDeviceEntity, async_all_device_entities
from .models import PermRequired, ProtectSetableKeysMixin, T
from .utils import async_get_is_highfps
_LOGGER = logging.getLogger(__name__)
@ -36,10 +37,6 @@ class ProtectSwitchEntityDescription(
_KEY_PRIVACY_MODE = "privacy_mode"
def _get_is_highfps(obj: Camera) -> bool:
return bool(obj.video_mode == VideoMode.HIGH_FPS)
async def _set_highfps(obj: Camera, value: bool) -> None:
if value:
await obj.set_video_mode(VideoMode.HIGH_FPS)
@ -84,7 +81,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
icon="mdi:video-high-definition",
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_highfps",
ufp_value_fn=_get_is_highfps,
ufp_value_fn=async_get_is_highfps,
ufp_set_method_fn=_set_highfps,
ufp_perm=PermRequired.WRITE,
),

View File

@ -9,8 +9,13 @@ from typing import Any
from pyunifiprotect.data import (
Bootstrap,
Camera,
Light,
LightModeEnableType,
LightModeType,
ProtectAdoptableDeviceModel,
ProtectDeviceModel,
VideoMode,
)
from homeassistant.core import HomeAssistant, callback
@ -104,3 +109,22 @@ def async_get_devices(
for device_type in model_type
for device in async_get_devices_by_type(bootstrap, device_type).values()
)
@callback
def async_get_is_highfps(obj: Camera) -> bool:
"""Return if camera has High FPS mode enabled."""
return bool(obj.video_mode == VideoMode.HIGH_FPS)
@callback
def async_get_light_motion_current(obj: Light) -> str:
"""Get light motion mode for Flood Light."""
if (
obj.light_mode_settings.mode == LightModeType.MOTION
and obj.light_mode_settings.enable_at == LightModeEnableType.DARK
):
return f"{LightModeType.MOTION.value}Dark"
return obj.light_mode_settings.mode.value

View File

@ -39,6 +39,9 @@ from .conftest import (
reset_objects,
)
LIGHT_SENSOR_WRITE = LIGHT_SENSORS[:2]
SENSE_SENSORS_WRITE = SENSE_SENSORS[:4]
@pytest.fixture(name="camera")
async def camera_fixture(
@ -230,7 +233,7 @@ async def test_binary_sensor_setup_light(
entity_registry = er.async_get(hass)
for description in LIGHT_SENSORS:
for description in LIGHT_SENSOR_WRITE:
unique_id, entity_id = ids_from_device_description(
Platform.BINARY_SENSOR, light, description
)
@ -328,7 +331,7 @@ async def test_binary_sensor_setup_sensor(
entity_registry = er.async_get(hass)
for description in SENSE_SENSORS:
for description in SENSE_SENSORS_WRITE:
unique_id, entity_id = ids_from_device_description(
Platform.BINARY_SENSOR, sensor, description
)
@ -356,7 +359,7 @@ async def test_binary_sensor_setup_sensor_none(
STATE_UNAVAILABLE,
STATE_OFF,
]
for index, description in enumerate(SENSE_SENSORS):
for index, description in enumerate(SENSE_SENSORS_WRITE):
unique_id, entity_id = ids_from_device_description(
Platform.BINARY_SENSOR, sensor_none, description
)
@ -419,7 +422,7 @@ async def test_binary_sensor_update_light_motion(
"""Test binary_sensor motion entity."""
_, entity_id = ids_from_device_description(
Platform.BINARY_SENSOR, light, LIGHT_SENSORS[1]
Platform.BINARY_SENSOR, light, LIGHT_SENSOR_WRITE[1]
)
event_metadata = EventMetadata(light_id=light.id)
@ -461,7 +464,7 @@ async def test_binary_sensor_update_mount_type_window(
"""Test binary_sensor motion entity."""
_, entity_id = ids_from_device_description(
Platform.BINARY_SENSOR, sensor, SENSE_SENSORS[0]
Platform.BINARY_SENSOR, sensor, SENSE_SENSORS_WRITE[0]
)
state = hass.states.get(entity_id)
@ -492,7 +495,7 @@ async def test_binary_sensor_update_mount_type_garage(
"""Test binary_sensor motion entity."""
_, entity_id = ids_from_device_description(
Platform.BINARY_SENSOR, sensor, SENSE_SENSORS[0]
Platform.BINARY_SENSOR, sensor, SENSE_SENSORS_WRITE[0]
)
state = hass.states.get(entity_id)

View File

@ -51,6 +51,9 @@ from .conftest import (
time_changed,
)
CAMERA_SENSORS_WRITE = CAMERA_SENSORS[:5]
SENSE_SENSORS_WRITE = SENSE_SENSORS[:8]
@pytest.fixture(name="sensor")
async def sensor_fixture(
@ -193,7 +196,7 @@ async def test_sensor_setup_sensor(
"10.0",
"none",
)
for index, description in enumerate(SENSE_SENSORS):
for index, description in enumerate(SENSE_SENSORS_WRITE):
if not description.entity_registry_enabled_default:
continue
unique_id, entity_id = ids_from_device_description(
@ -241,7 +244,7 @@ async def test_sensor_setup_sensor_none(
STATE_UNAVAILABLE,
STATE_UNAVAILABLE,
)
for index, description in enumerate(SENSE_SENSORS):
for index, description in enumerate(SENSE_SENSORS_WRITE):
if not description.entity_registry_enabled_default:
continue
unique_id, entity_id = ids_from_device_description(
@ -411,7 +414,7 @@ async def test_sensor_setup_camera(
):
"""Test sensor entity setup for camera devices."""
# 3 from all, 7 from camera, 12 NVR
assert_entity_counts(hass, Platform.SENSOR, 24, 13)
assert_entity_counts(hass, Platform.SENSOR, 25, 13)
entity_registry = er.async_get(hass)
@ -421,7 +424,7 @@ async def test_sensor_setup_camera(
"100.0",
"20.0",
)
for index, description in enumerate(CAMERA_SENSORS):
for index, description in enumerate(CAMERA_SENSORS_WRITE):
if not description.entity_registry_enabled_default:
continue
unique_id, entity_id = ids_from_device_description(
@ -536,7 +539,7 @@ async def test_sensor_update_motion(
):
"""Test sensor motion entity."""
# 3 from all, 7 from camera, 12 NVR
assert_entity_counts(hass, Platform.SENSOR, 24, 13)
assert_entity_counts(hass, Platform.SENSOR, 25, 13)
_, entity_id = ids_from_device_description(
Platform.SENSOR, camera, MOTION_SENSORS[0]
@ -584,7 +587,7 @@ async def test_sensor_update_alarm(
assert_entity_counts(hass, Platform.SENSOR, 22, 14)
_, entity_id = ids_from_device_description(
Platform.SENSOR, sensor, SENSE_SENSORS[4]
Platform.SENSOR, sensor, SENSE_SENSORS_WRITE[4]
)
event_metadata = EventMetadata(sensor_id=sensor.id, alarm_type="smoke")
@ -632,7 +635,7 @@ async def test_sensor_update_alarm_with_last_trip_time(
# Last Trip Time
unique_id, entity_id = ids_from_device_description(
Platform.SENSOR, sensor, SENSE_SENSORS[-3]
Platform.SENSOR, sensor, SENSE_SENSORS_WRITE[-3]
)
entity_registry = er.async_get(hass)