ha-core/homeassistant/components/unifiprotect/switch.py

301 lines
9.9 KiB
Python
Raw Normal View History

"""This component provides Switches for UniFi Protect."""
from __future__ import annotations
from dataclasses import dataclass
import logging
from typing import Any, Generic
from pyunifiprotect.data import Camera, RecordingMode, VideoMode
from pyunifiprotect.data.base import ProtectAdoptableDeviceModel
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
from .data import ProtectData
from .entity import ProtectDeviceEntity, async_all_device_entities
from .models import ProtectSetableKeysMixin, T
_LOGGER = logging.getLogger(__name__)
@dataclass
class ProtectSwitchEntityDescription(
ProtectSetableKeysMixin, SwitchEntityDescription, Generic[T]
):
"""Describes UniFi Protect Switch entity."""
_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)
else:
await obj.set_video_mode(VideoMode.DEFAULT)
ALL_DEVICES_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
ProtectSwitchEntityDescription(
key="ssh",
name="SSH Enabled",
icon="mdi:lock",
entity_registry_enabled_default=False,
entity_category=EntityCategory.CONFIG,
ufp_value="is_ssh_enabled",
ufp_set_method="set_ssh",
),
)
CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
ProtectSwitchEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_led_status",
ufp_value="led_settings.is_enabled",
ufp_set_method="set_status_light",
),
ProtectSwitchEntityDescription(
key="hdr_mode",
name="HDR Mode",
icon="mdi:brightness-7",
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_hdr",
ufp_value="hdr_mode",
ufp_set_method="set_hdr",
),
ProtectSwitchEntityDescription[Camera](
key="high_fps",
name="High FPS",
icon="mdi:video-high-definition",
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_highfps",
ufp_value_fn=_get_is_highfps,
ufp_set_method_fn=_set_highfps,
),
ProtectSwitchEntityDescription(
key=_KEY_PRIVACY_MODE,
name="Privacy Mode",
icon="mdi:eye-settings",
2022-03-31 11:06:07 +02:00
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_privacy_mask",
ufp_value="is_privacy_on",
),
ProtectSwitchEntityDescription(
key="system_sounds",
name="System Sounds",
icon="mdi:speaker",
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_speaker",
ufp_value="speaker_settings.are_system_sounds_enabled",
ufp_set_method="set_system_sounds",
),
ProtectSwitchEntityDescription(
key="osd_name",
name="Overlay: Show Name",
icon="mdi:fullscreen",
entity_category=EntityCategory.CONFIG,
ufp_value="osd_settings.is_name_enabled",
ufp_set_method="set_osd_name",
),
ProtectSwitchEntityDescription(
key="osd_date",
name="Overlay: Show Date",
icon="mdi:fullscreen",
entity_category=EntityCategory.CONFIG,
ufp_value="osd_settings.is_date_enabled",
ufp_set_method="set_osd_date",
),
ProtectSwitchEntityDescription(
key="osd_logo",
name="Overlay: Show Logo",
icon="mdi:fullscreen",
entity_category=EntityCategory.CONFIG,
ufp_value="osd_settings.is_logo_enabled",
ufp_set_method="set_osd_logo",
),
ProtectSwitchEntityDescription(
key="osd_bitrate",
name="Overlay: Show Bitrate",
icon="mdi:fullscreen",
entity_category=EntityCategory.CONFIG,
ufp_value="osd_settings.is_debug_enabled",
ufp_set_method="set_osd_bitrate",
),
ProtectSwitchEntityDescription(
key="smart_person",
name="Detections: Person",
icon="mdi:walk",
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_smart_detect",
ufp_value="is_person_detection_on",
ufp_set_method="set_person_detection",
),
ProtectSwitchEntityDescription(
key="smart_vehicle",
name="Detections: Vehicle",
icon="mdi:car",
entity_category=EntityCategory.CONFIG,
ufp_required_field="feature_flags.has_smart_detect",
ufp_value="is_vehicle_detection_on",
ufp_set_method="set_vehicle_detection",
),
)
SENSE_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
ProtectSwitchEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.CONFIG,
ufp_value="led_settings.is_enabled",
ufp_set_method="set_status_light",
),
ProtectSwitchEntityDescription(
key="motion",
name="Motion Detection",
icon="mdi:walk",
entity_category=EntityCategory.CONFIG,
ufp_value="motion_settings.is_enabled",
ufp_set_method="set_motion_status",
),
ProtectSwitchEntityDescription(
key="temperature",
name="Temperature Sensor",
icon="mdi:thermometer",
entity_category=EntityCategory.CONFIG,
ufp_value="temperature_settings.is_enabled",
ufp_set_method="set_temperature_status",
),
ProtectSwitchEntityDescription(
key="humidity",
name="Humidity Sensor",
icon="mdi:water-percent",
entity_category=EntityCategory.CONFIG,
ufp_value="humidity_settings.is_enabled",
ufp_set_method="set_humidity_status",
),
ProtectSwitchEntityDescription(
key="light",
name="Light Sensor",
icon="mdi:brightness-5",
entity_category=EntityCategory.CONFIG,
ufp_value="light_settings.is_enabled",
ufp_set_method="set_light_status",
),
ProtectSwitchEntityDescription(
key="alarm",
name="Alarm Sound Detection",
entity_category=EntityCategory.CONFIG,
ufp_value="alarm_settings.is_enabled",
ufp_set_method="set_alarm_status",
),
)
LIGHT_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
ProtectSwitchEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.CONFIG,
ufp_value="light_device_settings.is_indicator_enabled",
ufp_set_method="set_status_light",
),
)
DOORLOCK_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
ProtectSwitchEntityDescription(
key="status_light",
name="Status Light On",
icon="mdi:led-on",
entity_category=EntityCategory.CONFIG,
ufp_value="led_settings.is_enabled",
ufp_set_method="set_status_light",
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up sensors for UniFi Protect integration."""
data: ProtectData = hass.data[DOMAIN][entry.entry_id]
entities: list[ProtectDeviceEntity] = async_all_device_entities(
data,
ProtectSwitch,
all_descs=ALL_DEVICES_SWITCHES,
camera_descs=CAMERA_SWITCHES,
light_descs=LIGHT_SWITCHES,
sense_descs=SENSE_SWITCHES,
lock_descs=DOORLOCK_SWITCHES,
)
async_add_entities(entities)
class ProtectSwitch(ProtectDeviceEntity, SwitchEntity):
"""A UniFi Protect Switch."""
entity_description: ProtectSwitchEntityDescription
def __init__(
self,
data: ProtectData,
device: ProtectAdoptableDeviceModel,
description: ProtectSwitchEntityDescription,
) -> None:
"""Initialize an UniFi Protect Switch."""
super().__init__(data, device, description)
self._attr_name = f"{self.device.name} {self.entity_description.name}"
self._switch_type = self.entity_description.key
if not isinstance(self.device, Camera):
return
if self.entity_description.key == _KEY_PRIVACY_MODE:
if self.device.is_privacy_on:
self._previous_mic_level = 100
self._previous_record_mode = RecordingMode.ALWAYS
else:
self._previous_mic_level = self.device.mic_volume
self._previous_record_mode = self.device.recording_settings.mode
@property
def is_on(self) -> bool:
"""Return true if device is on."""
return self.entity_description.get_ufp_value(self.device) is True
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the device on."""
if self._switch_type == _KEY_PRIVACY_MODE:
assert isinstance(self.device, Camera)
self._previous_mic_level = self.device.mic_volume
self._previous_record_mode = self.device.recording_settings.mode
await self.device.set_privacy(True, 0, RecordingMode.NEVER)
else:
await self.entity_description.ufp_set(self.device, True)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the device off."""
if self._switch_type == _KEY_PRIVACY_MODE:
assert isinstance(self.device, Camera)
_LOGGER.debug("Setting Privacy Mode to false for %s", self.device.name)
await self.device.set_privacy(
False, self._previous_mic_level, self._previous_record_mode
)
else:
await self.entity_description.ufp_set(self.device, False)