core/homeassistant/components/ezviz/switch.py

178 lines
6.0 KiB
Python

"""Support for EZVIZ Switch sensors."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from pyezviz.constants import DeviceSwitchType, SupportExt
from pyezviz.exceptions import HTTPError, PyEzvizError
from homeassistant.components.switch import (
SwitchDeviceClass,
SwitchEntity,
SwitchEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DATA_COORDINATOR, DOMAIN
from .coordinator import EzvizDataUpdateCoordinator
from .entity import EzvizEntity
@dataclass(frozen=True, kw_only=True)
class EzvizSwitchEntityDescription(SwitchEntityDescription):
"""Describe a EZVIZ switch."""
supported_ext: str | None
SWITCH_TYPES: dict[int, EzvizSwitchEntityDescription] = {
3: EzvizSwitchEntityDescription(
key="3",
translation_key="status_light",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=None,
),
7: EzvizSwitchEntityDescription(
key="7",
translation_key="privacy",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportPtzPrivacy.value),
),
10: EzvizSwitchEntityDescription(
key="10",
translation_key="infrared_light",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportCloseInfraredLight.value),
),
21: EzvizSwitchEntityDescription(
key="21",
translation_key="sleep",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportSleep.value),
),
22: EzvizSwitchEntityDescription(
key="22",
translation_key="audio",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportAudioOnoff.value),
),
25: EzvizSwitchEntityDescription(
key="25",
translation_key="motion_tracking",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportIntelligentTrack.value),
),
29: EzvizSwitchEntityDescription(
key="29",
translation_key="all_day_video_recording",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportFulldayRecord.value),
),
32: EzvizSwitchEntityDescription(
key="32",
translation_key="auto_sleep",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportAutoSleep.value),
),
301: EzvizSwitchEntityDescription(
key="301",
translation_key="flicker_light_on_movement",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportActiveDefense.value),
),
305: EzvizSwitchEntityDescription(
key="305",
translation_key="pir_motion_activated_light",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportLightRelate.value),
),
306: EzvizSwitchEntityDescription(
key="306",
translation_key="tamper_alarm",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportTamperAlarm.value),
),
650: EzvizSwitchEntityDescription(
key="650",
translation_key="follow_movement",
device_class=SwitchDeviceClass.SWITCH,
supported_ext=str(SupportExt.SupportTracking.value),
),
}
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up EZVIZ switch based on a config entry."""
coordinator: EzvizDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][
DATA_COORDINATOR
]
async_add_entities(
EzvizSwitch(coordinator, camera, switch_number)
for camera in coordinator.data
for switch_number in coordinator.data[camera]["switches"]
if switch_number in SWITCH_TYPES
if SWITCH_TYPES[switch_number].supported_ext
in coordinator.data[camera]["supportExt"]
or SWITCH_TYPES[switch_number].supported_ext is None
)
class EzvizSwitch(EzvizEntity, SwitchEntity):
"""Representation of a EZVIZ sensor."""
def __init__(
self, coordinator: EzvizDataUpdateCoordinator, serial: str, switch_number: int
) -> None:
"""Initialize the switch."""
super().__init__(coordinator, serial)
self._switch_number = switch_number
self._attr_unique_id = (
f"{serial}_{self._camera_name}.{DeviceSwitchType(switch_number).name}"
)
self.entity_description = SWITCH_TYPES[switch_number]
self._attr_is_on = self.data["switches"][switch_number]
async def async_turn_on(self, **kwargs: Any) -> None:
"""Change a device switch on the camera."""
try:
if await self.hass.async_add_executor_job(
self.coordinator.ezviz_client.switch_status,
self._serial,
self._switch_number,
1,
):
self._attr_is_on = True
self.async_write_ha_state()
except (HTTPError, PyEzvizError) as err:
raise HomeAssistantError(f"Failed to turn on switch {self.name}") from err
async def async_turn_off(self, **kwargs: Any) -> None:
"""Change a device switch on the camera."""
try:
if await self.hass.async_add_executor_job(
self.coordinator.ezviz_client.switch_status,
self._serial,
self._switch_number,
0,
):
self._attr_is_on = False
self.async_write_ha_state()
except (HTTPError, PyEzvizError) as err:
raise HomeAssistantError(f"Failed to turn off switch {self.name}") from err
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self._attr_is_on = self.data["switches"].get(self._switch_number)
super()._handle_coordinator_update()