mirror of
https://github.com/home-assistant/core.git
synced 2026-05-28 03:06:30 +01:00
Migrate more UniFi Protect entities to public API (#171785)
Co-authored-by: RaHehl <rahehl@users.noreply.github.com>
This commit is contained in:
@@ -66,6 +66,14 @@ def _get_chime_duration(obj: Camera) -> int:
|
||||
return int(obj.chime_duration_seconds)
|
||||
|
||||
|
||||
async def _set_chime_volume(obj: Chime, value: float) -> None:
|
||||
"""Set chime volume per paired camera via the public API."""
|
||||
level = int(value)
|
||||
ring_settings = [setting.to_api_dict(volume=level) for setting in obj.ring_settings]
|
||||
if ring_settings:
|
||||
await obj.set_ring_settings_public(ring_settings)
|
||||
|
||||
|
||||
CAMERA_NUMBERS: tuple[ProtectNumberEntityDescription, ...] = (
|
||||
ProtectNumberEntityDescription(
|
||||
key="wdr_value",
|
||||
@@ -84,13 +92,13 @@ CAMERA_NUMBERS: tuple[ProtectNumberEntityDescription, ...] = (
|
||||
translation_key="microphone_level",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
ufp_min=0,
|
||||
ufp_min=1,
|
||||
ufp_max=100,
|
||||
ufp_step=1,
|
||||
ufp_required_field="has_mic",
|
||||
ufp_value="mic_volume",
|
||||
ufp_enabled="feature_flags.has_mic",
|
||||
ufp_set_method="set_mic_volume",
|
||||
ufp_set_method="set_mic_volume_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectNumberEntityDescription(
|
||||
@@ -221,7 +229,7 @@ DOORLOCK_NUMBERS: tuple[ProtectNumberEntityDescription, ...] = (
|
||||
)
|
||||
|
||||
CHIME_NUMBERS: tuple[ProtectNumberEntityDescription, ...] = (
|
||||
ProtectNumberEntityDescription(
|
||||
ProtectNumberEntityDescription[Chime](
|
||||
key="volume",
|
||||
translation_key="volume",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
@@ -230,7 +238,7 @@ CHIME_NUMBERS: tuple[ProtectNumberEntityDescription, ...] = (
|
||||
ufp_max=100,
|
||||
ufp_step=1,
|
||||
ufp_value="volume",
|
||||
ufp_set_method="set_volume",
|
||||
ufp_set_method_fn=_set_chime_volume,
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ from uiprotect.data import (
|
||||
MountType,
|
||||
ProtectAdoptableDeviceModel,
|
||||
PTZPatrol,
|
||||
PublicHdrMode,
|
||||
RecordingMode,
|
||||
Sensor,
|
||||
Viewer,
|
||||
@@ -184,11 +185,15 @@ async def _set_paired_camera(obj: Light | Sensor | Doorlock, camera_id: str) ->
|
||||
async def _set_doorbell_message(obj: Camera, message: str) -> None:
|
||||
if message.startswith(DoorbellMessageType.CUSTOM_MESSAGE.value):
|
||||
message = message.rsplit(":", maxsplit=1)[-1]
|
||||
await obj.set_lcd_text(DoorbellMessageType.CUSTOM_MESSAGE, text=message)
|
||||
await obj.set_lcd_message_public(
|
||||
DoorbellMessageType.CUSTOM_MESSAGE, text=message
|
||||
)
|
||||
elif message == TYPE_EMPTY_VALUE:
|
||||
# Public API has no endpoint to clear the LCD message; fall back to
|
||||
# the non-deprecated legacy helper.
|
||||
await obj.set_lcd_text(None)
|
||||
else:
|
||||
await obj.set_lcd_text(DoorbellMessageType(message))
|
||||
await obj.set_lcd_message_public(DoorbellMessageType(message))
|
||||
|
||||
|
||||
async def _set_liveview(obj: Viewer, liveview_id: str) -> None:
|
||||
@@ -206,6 +211,18 @@ async def _set_ptz_patrol(obj: Camera, patrol_slot: str) -> None:
|
||||
await obj.ptz_patrol_start_public(slot=slot)
|
||||
|
||||
|
||||
_HDR_MODE_MAP = {
|
||||
"auto": PublicHdrMode.AUTO,
|
||||
"always": PublicHdrMode.ON,
|
||||
"off": PublicHdrMode.OFF,
|
||||
}
|
||||
|
||||
|
||||
async def _set_hdr_mode(obj: Camera, mode: str) -> None:
|
||||
"""Set HDR mode via the public API."""
|
||||
await obj.set_hdr_mode_public(_HDR_MODE_MAP[mode])
|
||||
|
||||
|
||||
PTZ_PATROL_DESCRIPTION = ProtectSelectEntityDescription[Camera](
|
||||
key=_KEY_PTZ_PATROL,
|
||||
translation_key="ptz_patrol",
|
||||
@@ -258,14 +275,14 @@ CAMERA_SELECTS: tuple[ProtectSelectEntityDescription, ...] = (
|
||||
ufp_set_method="set_chime_type",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSelectEntityDescription(
|
||||
ProtectSelectEntityDescription[Camera](
|
||||
key="hdr_mode",
|
||||
translation_key="hdr_mode",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
ufp_required_field="feature_flags.has_hdr",
|
||||
ufp_options=HDR_MODES,
|
||||
ufp_value="hdr_mode_display",
|
||||
ufp_set_method="set_hdr_mode",
|
||||
ufp_set_method_fn=_set_hdr_mode,
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
)
|
||||
|
||||
@@ -572,7 +572,7 @@
|
||||
"detections_baby_cry": {
|
||||
"name": "[%key:component::unifiprotect::entity::binary_sensor::detections_baby_cry::name%]"
|
||||
},
|
||||
"detections_barking": {
|
||||
"detections_bark": {
|
||||
"name": "[%key:component::unifiprotect::entity::binary_sensor::detections_barking::name%]"
|
||||
},
|
||||
"detections_car_alarm": {
|
||||
|
||||
@@ -9,6 +9,7 @@ from uiprotect.data import (
|
||||
Camera,
|
||||
ModelType,
|
||||
ProtectAdoptableDeviceModel,
|
||||
PublicHdrMode,
|
||||
PublicRelayOutput,
|
||||
RecordingMode,
|
||||
Relay,
|
||||
@@ -53,7 +54,11 @@ class ProtectSwitchEntityDescription(
|
||||
|
||||
|
||||
async def _set_highfps(obj: Camera, value: bool) -> None:
|
||||
await obj.set_video_mode(VideoMode.HIGH_FPS if value else VideoMode.DEFAULT)
|
||||
await obj.set_video_mode_public(VideoMode.HIGH_FPS if value else VideoMode.DEFAULT)
|
||||
|
||||
|
||||
async def _set_hdr(obj: Camera, value: bool) -> None:
|
||||
await obj.set_hdr_mode_public(PublicHdrMode.AUTO if value else PublicHdrMode.OFF)
|
||||
|
||||
|
||||
CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
@@ -72,17 +77,17 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
ufp_required_field="feature_flags.has_led_status",
|
||||
ufp_value="led_settings.is_enabled",
|
||||
ufp_set_method="set_status_light",
|
||||
ufp_set_method="set_status_light_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
ProtectSwitchEntityDescription[Camera](
|
||||
key="hdr_mode",
|
||||
translation_key="hdr_mode",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
ufp_required_field="feature_flags.has_hdr",
|
||||
ufp_value="hdr_mode",
|
||||
ufp_set_method="set_hdr",
|
||||
ufp_set_method_fn=_set_hdr,
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription[Camera](
|
||||
@@ -109,7 +114,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
translation_key="overlay_show_name",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
ufp_value="osd_settings.is_name_enabled",
|
||||
ufp_set_method="set_osd_name",
|
||||
ufp_set_method="set_osd_name_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -117,7 +122,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
translation_key="overlay_show_date",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
ufp_value="osd_settings.is_date_enabled",
|
||||
ufp_set_method="set_osd_date",
|
||||
ufp_set_method="set_osd_date_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -125,7 +130,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
translation_key="overlay_show_logo",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
ufp_value="osd_settings.is_logo_enabled",
|
||||
ufp_set_method="set_osd_logo",
|
||||
ufp_set_method="set_osd_logo_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -133,7 +138,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
translation_key="overlay_show_nerd_mode",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
ufp_value="osd_settings.is_debug_enabled",
|
||||
ufp_set_method="set_osd_bitrate",
|
||||
ufp_set_method="set_osd_nerd_mode_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -161,7 +166,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_person",
|
||||
ufp_value="is_person_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_person_detection",
|
||||
ufp_set_method="set_person_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -171,7 +176,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_vehicle",
|
||||
ufp_value="is_vehicle_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_vehicle_detection",
|
||||
ufp_set_method="set_vehicle_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -181,7 +186,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_animal",
|
||||
ufp_value="is_animal_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_animal_detection",
|
||||
ufp_set_method="set_animal_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -191,7 +196,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_package",
|
||||
ufp_value="is_package_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_package_detection",
|
||||
ufp_set_method="set_package_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -201,7 +206,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_license_plate",
|
||||
ufp_value="is_license_plate_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_license_plate_detection",
|
||||
ufp_set_method="set_license_plate_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -211,7 +216,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_smoke",
|
||||
ufp_value="is_smoke_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_smoke_detection",
|
||||
ufp_set_method="set_smoke_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -221,7 +226,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_co",
|
||||
ufp_value="is_co_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_cmonx_detection",
|
||||
ufp_set_method="set_co_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -231,7 +236,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_siren",
|
||||
ufp_value="is_siren_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_siren_detection",
|
||||
ufp_set_method="set_siren_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -241,7 +246,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_baby_cry",
|
||||
ufp_value="is_baby_cry_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_baby_cry_detection",
|
||||
ufp_set_method="set_baby_cry_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -251,7 +256,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_speaking",
|
||||
ufp_value="is_speaking_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_speaking_detection",
|
||||
ufp_set_method="set_speaking_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -261,7 +266,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_bark",
|
||||
ufp_value="is_bark_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_bark_detection",
|
||||
ufp_set_method="set_bark_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -271,7 +276,8 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_car_alarm",
|
||||
ufp_value="is_car_alarm_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_car_alarm_detection",
|
||||
# Public API renamed "car alarm" to "burglar"; internal model keeps the legacy name.
|
||||
ufp_set_method="set_burglar_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -281,7 +287,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_car_horn",
|
||||
ufp_value="is_car_horn_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_car_horn_detection",
|
||||
ufp_set_method="set_car_horn_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
@@ -291,7 +297,7 @@ CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
|
||||
ufp_required_field="can_detect_glass_break",
|
||||
ufp_value="is_glass_break_detection_on",
|
||||
ufp_enabled="is_recording_enabled",
|
||||
ufp_set_method="set_glass_break_detection",
|
||||
ufp_set_method="set_glass_break_detection_public",
|
||||
ufp_perm=PermRequired.WRITE,
|
||||
),
|
||||
ProtectSwitchEntityDescription(
|
||||
|
||||
@@ -328,6 +328,41 @@ async def test_chime_ring_volume_set_value(
|
||||
mock_method.assert_called_once_with(doorbell, 80)
|
||||
|
||||
|
||||
async def test_chime_volume_set_value(
|
||||
hass: HomeAssistant,
|
||||
ufp: MockUFPFixture,
|
||||
chime: Chime,
|
||||
doorbell: Camera,
|
||||
) -> None:
|
||||
"""Test setting overall chime volume calls public ring-settings API."""
|
||||
_setup_chime_with_doorbell(chime, doorbell, volume=40)
|
||||
|
||||
await init_entry(hass, ufp, [chime, doorbell], regenerate_ids=False)
|
||||
|
||||
entity_id = "number.test_chime_volume"
|
||||
|
||||
with patch_ufp_method(
|
||||
chime, "set_ring_settings_public", new_callable=AsyncMock
|
||||
) as mock_method:
|
||||
await hass.services.async_call(
|
||||
"number",
|
||||
"set_value",
|
||||
{ATTR_ENTITY_ID: entity_id, "value": 75.0},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_method.assert_called_once_with(
|
||||
[
|
||||
{
|
||||
"cameraId": doorbell.id,
|
||||
"volume": 75,
|
||||
"repeatTimes": 1,
|
||||
"ringtoneId": "test-ringtone-id",
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
async def test_chime_ring_volume_multiple_cameras(
|
||||
hass: HomeAssistant,
|
||||
ufp: MockUFPFixture,
|
||||
|
||||
@@ -19,6 +19,7 @@ from uiprotect.data import (
|
||||
NvrArmModeStatus,
|
||||
PTZPatrol,
|
||||
PublicBootstrap,
|
||||
PublicHdrMode,
|
||||
RecordingMode,
|
||||
Viewer,
|
||||
)
|
||||
@@ -454,7 +455,7 @@ async def test_select_set_option_camera_doorbell_custom(
|
||||
)
|
||||
|
||||
with patch_ufp_method(
|
||||
doorbell, "set_lcd_text", new_callable=AsyncMock
|
||||
doorbell, "set_lcd_message_public", new_callable=AsyncMock
|
||||
) as mock_method:
|
||||
await hass.services.async_call(
|
||||
"select",
|
||||
@@ -480,9 +481,14 @@ async def test_select_set_option_camera_doorbell_unifi(
|
||||
hass, Platform.SELECT, doorbell, CAMERA_SELECTS[2]
|
||||
)
|
||||
|
||||
with patch_ufp_method(
|
||||
doorbell, "set_lcd_text", new_callable=AsyncMock
|
||||
) as mock_method:
|
||||
with (
|
||||
patch_ufp_method(
|
||||
doorbell, "set_lcd_message_public", new_callable=AsyncMock
|
||||
) as mock_public,
|
||||
patch_ufp_method(
|
||||
doorbell, "set_lcd_text", new_callable=AsyncMock
|
||||
) as mock_legacy,
|
||||
):
|
||||
await hass.services.async_call(
|
||||
"select",
|
||||
"select_option",
|
||||
@@ -493,7 +499,7 @@ async def test_select_set_option_camera_doorbell_unifi(
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_method.assert_called_once_with(DoorbellMessageType.LEAVE_PACKAGE_AT_DOOR)
|
||||
mock_public.assert_called_once_with(DoorbellMessageType.LEAVE_PACKAGE_AT_DOOR)
|
||||
|
||||
await hass.services.async_call(
|
||||
"select",
|
||||
@@ -505,7 +511,7 @@ async def test_select_set_option_camera_doorbell_unifi(
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_method.assert_called_with(None)
|
||||
mock_legacy.assert_called_once_with(None)
|
||||
|
||||
|
||||
async def test_select_set_option_camera_doorbell_default(
|
||||
@@ -536,6 +542,44 @@ async def test_select_set_option_camera_doorbell_default(
|
||||
mock_method.assert_called_once_with(None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("option", "expected"),
|
||||
[
|
||||
pytest.param("auto", PublicHdrMode.AUTO, id="auto"),
|
||||
pytest.param("always", PublicHdrMode.ON, id="always"),
|
||||
pytest.param("off", PublicHdrMode.OFF, id="off"),
|
||||
],
|
||||
)
|
||||
async def test_select_set_option_camera_hdr_mode(
|
||||
hass: HomeAssistant,
|
||||
ufp: MockUFPFixture,
|
||||
doorbell: Camera,
|
||||
option: str,
|
||||
expected: PublicHdrMode,
|
||||
) -> None:
|
||||
"""Test HDR mode select calls public API with mapped value."""
|
||||
|
||||
await init_entry(hass, ufp, [doorbell])
|
||||
assert_entity_counts(hass, Platform.SELECT, 5, 5)
|
||||
|
||||
description = next(d for d in CAMERA_SELECTS if d.key == "hdr_mode")
|
||||
_, entity_id = await ids_from_device_description(
|
||||
hass, Platform.SELECT, doorbell, description
|
||||
)
|
||||
|
||||
with patch_ufp_method(
|
||||
doorbell, "set_hdr_mode_public", new_callable=AsyncMock
|
||||
) as mock_method:
|
||||
await hass.services.async_call(
|
||||
"select",
|
||||
"select_option",
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: option},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
mock_method.assert_called_once_with(expected)
|
||||
|
||||
|
||||
async def test_select_set_option_viewer(
|
||||
hass: HomeAssistant, ufp: MockUFPFixture, viewer: Viewer, liveview: Liveview
|
||||
) -> None:
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
"""Test the UniFi Protect switch platform."""
|
||||
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
from unittest.mock import AsyncMock, Mock, call
|
||||
|
||||
import pytest
|
||||
from uiprotect.data import Camera, Light, Permission, RecordingMode, VideoMode
|
||||
from uiprotect.data import (
|
||||
Camera,
|
||||
Light,
|
||||
Permission,
|
||||
PublicHdrMode,
|
||||
RecordingMode,
|
||||
SmartDetectAudioType,
|
||||
SmartDetectObjectType,
|
||||
VideoMode,
|
||||
)
|
||||
from uiprotect.exceptions import ClientError, NotAuthorized
|
||||
|
||||
from homeassistant.components.unifiprotect.const import DEFAULT_ATTRIBUTION
|
||||
@@ -363,7 +372,7 @@ async def test_switch_camera_highfps(
|
||||
)
|
||||
|
||||
with patch_ufp_method(
|
||||
doorbell, "set_video_mode", new_callable=AsyncMock
|
||||
doorbell, "set_video_mode_public", new_callable=AsyncMock
|
||||
) as mock_method:
|
||||
await hass.services.async_call(
|
||||
"switch", "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
@@ -378,6 +387,102 @@ async def test_switch_camera_highfps(
|
||||
mock_method.assert_called_with(VideoMode.DEFAULT)
|
||||
|
||||
|
||||
CAMERA_SWITCHES_DETECTIONS_EXTRA = [
|
||||
d
|
||||
for d in CAMERA_SWITCHES
|
||||
if d.translation_key.startswith("detections_")
|
||||
and d.key
|
||||
not in {
|
||||
"detections_motion",
|
||||
"detections_person",
|
||||
"detections_vehicle",
|
||||
"detections_animal",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
async def test_switch_camera_hdr(
|
||||
hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera
|
||||
) -> None:
|
||||
"""Tests HDR mode switch uses the public API helper."""
|
||||
|
||||
await init_entry(hass, ufp, [doorbell])
|
||||
assert_entity_counts(hass, Platform.SWITCH, 17, 15)
|
||||
|
||||
description = next(d for d in CAMERA_SWITCHES if d.key == "hdr_mode")
|
||||
|
||||
_, entity_id = await ids_from_device_description(
|
||||
hass, Platform.SWITCH, doorbell, description
|
||||
)
|
||||
await enable_entity(hass, ufp.entry.entry_id, entity_id)
|
||||
|
||||
with patch_ufp_method(
|
||||
doorbell, "set_hdr_mode_public", new_callable=AsyncMock
|
||||
) as mock_method:
|
||||
await hass.services.async_call(
|
||||
"switch", "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
await hass.services.async_call(
|
||||
"switch", "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
|
||||
mock_method.assert_has_calls(
|
||||
[call(PublicHdrMode.AUTO), call(PublicHdrMode.OFF)]
|
||||
)
|
||||
assert mock_method.call_count == 2
|
||||
|
||||
|
||||
@pytest.mark.parametrize("description", CAMERA_SWITCHES_DETECTIONS_EXTRA)
|
||||
async def test_switch_camera_detections_public_api(
|
||||
hass: HomeAssistant,
|
||||
ufp: MockUFPFixture,
|
||||
doorbell: Camera,
|
||||
description: ProtectSwitchEntityDescription,
|
||||
) -> None:
|
||||
"""Tests detection switches call the public API setters."""
|
||||
|
||||
doorbell.feature_flags.smart_detect_types = [
|
||||
SmartDetectObjectType.PERSON,
|
||||
SmartDetectObjectType.VEHICLE,
|
||||
SmartDetectObjectType.ANIMAL,
|
||||
SmartDetectObjectType.PACKAGE,
|
||||
SmartDetectObjectType.LICENSE_PLATE,
|
||||
]
|
||||
doorbell.feature_flags.smart_detect_audio_types = [
|
||||
SmartDetectAudioType.SMOKE,
|
||||
SmartDetectAudioType.CMONX,
|
||||
SmartDetectAudioType.SIREN,
|
||||
SmartDetectAudioType.BABY_CRY,
|
||||
SmartDetectAudioType.SPEAK,
|
||||
SmartDetectAudioType.BARK,
|
||||
SmartDetectAudioType.BURGLAR,
|
||||
SmartDetectAudioType.CAR_HORN,
|
||||
SmartDetectAudioType.GLASS_BREAK,
|
||||
]
|
||||
|
||||
await init_entry(hass, ufp, [doorbell])
|
||||
|
||||
assert description.ufp_set_method is not None
|
||||
assert description.ufp_set_method.endswith("_public")
|
||||
|
||||
_, entity_id = await ids_from_device_description(
|
||||
hass, Platform.SWITCH, doorbell, description
|
||||
)
|
||||
|
||||
with patch_ufp_method(
|
||||
doorbell, description.ufp_set_method, new_callable=AsyncMock
|
||||
) as mock_method:
|
||||
await hass.services.async_call(
|
||||
"switch", "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
await hass.services.async_call(
|
||||
"switch", "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||
)
|
||||
|
||||
mock_method.assert_has_calls([call(True), call(False)])
|
||||
assert mock_method.call_count == 2
|
||||
|
||||
|
||||
async def test_switch_camera_privacy(
|
||||
hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera
|
||||
) -> None:
|
||||
|
||||
Reference in New Issue
Block a user