"""Support for EZVIZ select controls.""" from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass from typing import cast from pyezvizapi.constants import ( BatteryCameraWorkMode, DeviceCatagories, DeviceSwitchType, SoundMode, SupportExt, ) from pyezvizapi.exceptions import HTTPError, PyEzvizError from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from .coordinator import EzvizConfigEntry, EzvizDataUpdateCoordinator from .entity import EzvizEntity PARALLEL_UPDATES = 1 @dataclass(frozen=True, kw_only=True) class EzvizSelectEntityDescription(SelectEntityDescription): """Describe a EZVIZ Select entity.""" supported_switch: int current_option: Callable[[EzvizSelect], str | None] select_option: Callable[[EzvizSelect, str, str], None] def alarm_sound_mode_current_option(ezvizSelect: EzvizSelect) -> str | None: """Return the selected entity option to represent the entity state.""" sound_mode_value = getattr( SoundMode, ezvizSelect.data[ezvizSelect.entity_description.key] ).value if sound_mode_value in [0, 1, 2]: return ezvizSelect.options[sound_mode_value] return None def alarm_sound_mode_select_option( ezvizSelect: EzvizSelect, serial: str, option: str ) -> None: """Change the selected option.""" sound_mode_value = ezvizSelect.options.index(option) ezvizSelect.coordinator.ezviz_client.alarm_sound(serial, sound_mode_value, 1) ALARM_SOUND_MODE_SELECT_TYPE = EzvizSelectEntityDescription( key="alarm_sound_mod", translation_key="alarm_sound_mode", entity_category=EntityCategory.CONFIG, options=["soft", "intensive", "silent"], supported_switch=DeviceSwitchType.ALARM_TONE.value, current_option=alarm_sound_mode_current_option, select_option=alarm_sound_mode_select_option, ) def battery_work_mode_current_option(ezvizSelect: EzvizSelect) -> str | None: """Return the selected entity option to represent the entity state.""" battery_work_mode = getattr( BatteryCameraWorkMode, ezvizSelect.data[ezvizSelect.entity_description.key], BatteryCameraWorkMode.UNKNOWN, ) if battery_work_mode == BatteryCameraWorkMode.UNKNOWN: return None return battery_work_mode.name.lower() def battery_work_mode_select_option( ezvizSelect: EzvizSelect, serial: str, option: str ) -> None: """Change the selected option.""" battery_work_mode = getattr(BatteryCameraWorkMode, option.upper()) ezvizSelect.coordinator.ezviz_client.set_battery_camera_work_mode( serial, battery_work_mode.value ) BATTERY_WORK_MODE_SELECT_TYPE = EzvizSelectEntityDescription( key="battery_camera_work_mode", translation_key="battery_camera_work_mode", icon="mdi:battery-sync", entity_category=EntityCategory.CONFIG, options=[ "plugged_in", "high_performance", "power_save", "super_power_save", "custom", ], supported_switch=-1, current_option=battery_work_mode_current_option, select_option=battery_work_mode_select_option, ) SELECT_TYPES = [ALARM_SOUND_MODE_SELECT_TYPE, BATTERY_WORK_MODE_SELECT_TYPE] async def async_setup_entry( hass: HomeAssistant, entry: EzvizConfigEntry, async_add_entities: AddConfigEntryEntitiesCallback, ) -> None: """Set up EZVIZ select entities based on a config entry.""" coordinator = entry.runtime_data entities = [ EzvizSelect(coordinator, camera, ALARM_SOUND_MODE_SELECT_TYPE) for camera in coordinator.data for switch in coordinator.data[camera]["switches"] if switch == ALARM_SOUND_MODE_SELECT_TYPE.supported_switch ] for camera in coordinator.data: device_category = coordinator.data[camera].get("device_category") supportExt = coordinator.data[camera].get("supportExt") if ( device_category == DeviceCatagories.BATTERY_CAMERA_DEVICE_CATEGORY.value and supportExt and str(SupportExt.SupportBatteryManage.value) in supportExt ): entities.append( EzvizSelect(coordinator, camera, BATTERY_WORK_MODE_SELECT_TYPE) ) async_add_entities(entities) class EzvizSelect(EzvizEntity, SelectEntity): """Representation of a EZVIZ select entity.""" def __init__( self, coordinator: EzvizDataUpdateCoordinator, serial: str, description: EzvizSelectEntityDescription, ) -> None: """Initialize the select entity.""" super().__init__(coordinator, serial) self._attr_unique_id = f"{serial}_{description.key}" self.entity_description = description @property def current_option(self) -> str | None: """Return the selected entity option to represent the entity state.""" desc = cast(EzvizSelectEntityDescription, self.entity_description) return desc.current_option(self) def select_option(self, option: str) -> None: """Change the selected option.""" desc = cast(EzvizSelectEntityDescription, self.entity_description) try: return desc.select_option(self, self._serial, option) except (HTTPError, PyEzvizError) as err: raise HomeAssistantError(f"Cannot select option for {desc.key}") from err