From 6473069be1cba92ebda2afd22db487fa5ac58a9a Mon Sep 17 00:00:00 2001 From: Christopher Bailey Date: Wed, 12 Jan 2022 13:55:44 -0500 Subject: [PATCH] Add Chime Type select for UniFi Protect (#63993) --- .../components/unifiprotect/number.py | 12 ------------ .../components/unifiprotect/select.py | 18 ++++++++++++++++++ tests/components/unifiprotect/test_number.py | 7 ++----- tests/components/unifiprotect/test_select.py | 9 ++++++--- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/unifiprotect/number.py b/homeassistant/components/unifiprotect/number.py index b5552a9b5e7..429844b52dd 100644 --- a/homeassistant/components/unifiprotect/number.py +++ b/homeassistant/components/unifiprotect/number.py @@ -82,18 +82,6 @@ CAMERA_NUMBERS: tuple[ProtectNumberEntityDescription, ...] = ( ufp_value="isp_settings.zoom_position", ufp_set_method="set_camera_zoom", ), - ProtectNumberEntityDescription( - key="duration", - name="Chime Duration", - icon="mdi:camera-timer", - entity_category=EntityCategory.CONFIG, - ufp_min=0, - ufp_max=10000, - ufp_step=100, - ufp_required_field="feature_flags.has_chime", - ufp_value="chime_duration", - ufp_set_method="set_chime_duration", - ), ) LIGHT_NUMBERS: tuple[ProtectNumberEntityDescription, ...] = ( diff --git a/homeassistant/components/unifiprotect/select.py b/homeassistant/components/unifiprotect/select.py index 20b02dbc5d8..bd9ec7cddd5 100644 --- a/homeassistant/components/unifiprotect/select.py +++ b/homeassistant/components/unifiprotect/select.py @@ -19,6 +19,7 @@ from pyunifiprotect.data import ( RecordingMode, Viewer, ) +from pyunifiprotect.data.types import ChimeType import voluptuous as vol from homeassistant.components.select import SelectEntity, SelectEntityDescription @@ -45,6 +46,12 @@ INFRARED_MODES = [ {"id": IRLEDMode.OFF.value, "name": "Always Disable"}, ] +CHIME_TYPES = [ + {"id": ChimeType.NONE.value, "name": "None"}, + {"id": ChimeType.MECHINCAL.value, "name": "Mechanical"}, + {"id": ChimeType.DIGITAL.value, "name": "Digital"}, +] + LIGHT_MODE_MOTION = "On Motion - Always" LIGHT_MODE_MOTION_DARK = "On Motion - When Dark" LIGHT_MODE_DARK = "When Dark" @@ -212,6 +219,17 @@ CAMERA_SELECTS: tuple[ProtectSelectEntityDescription, ...] = ( ufp_options_callable=_get_doorbell_options, ufp_set_method_fn=_set_doorbell_message, ), + ProtectSelectEntityDescription( + key="chime_type", + name="Chime Type", + icon="mdi:bell", + entity_category=EntityCategory.CONFIG, + ufp_required_field="feature_flags.has_chime", + ufp_options=CHIME_TYPES, + ufp_enum_type=ChimeType, + ufp_value="chime_type", + ufp_set_method="set_chime_type", + ), ) LIGHT_SELECTS: tuple[ProtectSelectEntityDescription, ...] = ( diff --git a/tests/components/unifiprotect/test_number.py b/tests/components/unifiprotect/test_number.py index 76bd2ec34b9..d3dfc7b3405 100644 --- a/tests/components/unifiprotect/test_number.py +++ b/tests/components/unifiprotect/test_number.py @@ -70,7 +70,6 @@ async def camera_fixture( camera_obj.channels[1]._api = mock_entry.api camera_obj.channels[2]._api = mock_entry.api camera_obj.name = "Test Camera" - camera_obj.feature_flags.has_chime = True camera_obj.feature_flags.can_optical_zoom = True camera_obj.feature_flags.has_mic = True # has_wdr is an the inverse of has HDR @@ -78,7 +77,6 @@ async def camera_fixture( camera_obj.isp_settings.wdr = 0 camera_obj.mic_volume = 0 camera_obj.isp_settings.zoom_position = 0 - camera_obj.chime_duration = 0 mock_entry.api.bootstrap.reset_objects() mock_entry.api.bootstrap.cameras = { @@ -88,7 +86,7 @@ async def camera_fixture( await hass.config_entries.async_setup(mock_entry.entry.entry_id) await hass.async_block_till_done() - assert_entity_counts(hass, Platform.NUMBER, 4, 4) + assert_entity_counts(hass, Platform.NUMBER, 3, 3) yield camera_obj @@ -152,7 +150,6 @@ async def test_number_setup_camera_none( camera_obj.channels[1]._api = mock_entry.api camera_obj.channels[2]._api = mock_entry.api camera_obj.name = "Test Camera" - camera_obj.feature_flags.has_chime = False camera_obj.feature_flags.can_optical_zoom = False camera_obj.feature_flags.has_mic = False # has_wdr is an the inverse of has HDR @@ -217,7 +214,7 @@ async def test_number_light_sensitivity(hass: HomeAssistant, light: Light): async def test_number_light_duration(hass: HomeAssistant, light: Light): - """Test chime duration number entity for lights.""" + """Test auto-shutoff duration number entity for lights.""" description = LIGHT_NUMBERS[1] diff --git a/tests/components/unifiprotect/test_select.py b/tests/components/unifiprotect/test_select.py index 1b216b1642b..a328e92835d 100644 --- a/tests/components/unifiprotect/test_select.py +++ b/tests/components/unifiprotect/test_select.py @@ -93,9 +93,11 @@ async def camera_fixture( camera_obj.channels[2]._api = mock_entry.api camera_obj.name = "Test Camera" camera_obj.feature_flags.has_lcd_screen = True + camera_obj.feature_flags.has_chime = True camera_obj.recording_settings.mode = RecordingMode.ALWAYS camera_obj.isp_settings.ir_led_mode = IRLEDMode.AUTO camera_obj.lcd_message = None + camera_obj.chime_duration = 0 mock_entry.api.bootstrap.reset_objects() mock_entry.api.bootstrap.cameras = { @@ -105,7 +107,7 @@ async def camera_fixture( await hass.config_entries.async_setup(mock_entry.entry.entry_id) await hass.async_block_till_done() - assert_entity_counts(hass, Platform.SELECT, 3, 3) + assert_entity_counts(hass, Platform.SELECT, 4, 4) yield camera_obj @@ -140,7 +142,7 @@ async def light_fixture( await hass.config_entries.async_reload(mock_entry.entry.entry_id) await hass.async_block_till_done() - assert_entity_counts(hass, Platform.SELECT, 5, 5) + assert_entity_counts(hass, Platform.SELECT, 6, 6) yield light_obj @@ -163,6 +165,7 @@ async def camera_none_fixture( camera_obj.channels[2]._api = mock_entry.api camera_obj.name = "Test Camera" camera_obj.feature_flags.has_lcd_screen = False + camera_obj.feature_flags.has_chime = False camera_obj.recording_settings.mode = RecordingMode.ALWAYS camera_obj.isp_settings.ir_led_mode = IRLEDMode.AUTO @@ -235,7 +238,7 @@ async def test_select_setup_camera_all( """Test select entity setup for camera devices (all features).""" entity_registry = er.async_get(hass) - expected_values = ("Always", "Auto", "Default Message (Welcome)") + expected_values = ("Always", "Auto", "Default Message (Welcome)", "None") for index, description in enumerate(CAMERA_SELECTS): unique_id, entity_id = ids_from_device_description(