Skip to content

Commit

Permalink
Add entity description to EZVIZ SwitchEntity (home-assistant#95672)
Browse files Browse the repository at this point in the history
* Initial commit

* Update switch entity

* Add entity description

* Redundant get. Key will always be there.

* fixed dumb condition mistake.

* Removed names from entity description

* Implement suggestions

* async_add_entities has iterator so cleanup

* Update strings.json
  • Loading branch information
RenierM26 authored Jul 29, 2023
1 parent 750260b commit f52876c
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 34 deletions.
38 changes: 38 additions & 0 deletions homeassistant/components/ezviz/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,44 @@
"last_alarm_type_name": {
"name": "Last alarm type name"
}
},
"switch": {
"status_light": {
"name": "Status light"
},
"privacy": {
"name": "Privacy"
},
"infrared_light": {
"name": "Infrared light"
},
"sleep": {
"name": "Sleep"
},
"audio": {
"name": "Audio"
},
"motion_tracking": {
"name": "Motion tracking"
},
"all_day_video_recording": {
"name": "All day video recording"
},
"auto_sleep": {
"name": "Auto sleep"
},
"flicker_light_on_movement": {
"name": "Flicker light on movement"
},
"pir_motion_activated_light": {
"name": "PIR motion activated light"
},
"tamper_alarm": {
"name": "Tamper alarm"
},
"follow_movement": {
"name": "Follow movement"
}
}
},
"services": {
Expand Down
169 changes: 135 additions & 34 deletions homeassistant/components/ezviz/switch.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,117 @@
"""Support for EZVIZ Switch sensors."""
from __future__ import annotations

from dataclasses import dataclass
from typing import Any

from pyezviz.constants import DeviceSwitchType
from pyezviz.constants import DeviceSwitchType, SupportExt
from pyezviz.exceptions import HTTPError, PyEzvizError

from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
from homeassistant.components.switch import (
SwitchDeviceClass,
SwitchEntity,
SwitchEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
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
class EzvizSwitchEntityDescriptionMixin:
"""Mixin values for EZVIZ Switch entities."""

supported_ext: str | None


@dataclass
class EzvizSwitchEntityDescription(
SwitchEntityDescription, EzvizSwitchEntityDescriptionMixin
):
"""Describe a EZVIZ switch."""


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:
Expand All @@ -24,61 +120,66 @@ async def async_setup_entry(
DATA_COORDINATOR
]

supported_switches = {switches.value for switches in DeviceSwitchType}

async_add_entities(
[
EzvizSwitch(coordinator, camera, switch)
for camera in coordinator.data
for switch in coordinator.data[camera].get("switches")
if switch in supported_switches
]
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."""

_attr_device_class = SwitchDeviceClass.SWITCH
_attr_has_entity_name = True

def __init__(
self, coordinator: EzvizDataUpdateCoordinator, serial: str, switch: str
self, coordinator: EzvizDataUpdateCoordinator, serial: str, switch_number: int
) -> None:
"""Initialize the switch."""
super().__init__(coordinator, serial)
self._name = switch
self._attr_name = f"{self._camera_name} {DeviceSwitchType(switch).name.title()}"
self._switch_number = switch_number
self._attr_unique_id = (
f"{serial}_{self._camera_name}.{DeviceSwitchType(switch).name}"
f"{serial}_{self._camera_name}.{DeviceSwitchType(switch_number).name}"
)

@property
def is_on(self) -> bool:
"""Return the state of the switch."""
return self.data["switches"][self._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:
update_ok = await self.hass.async_add_executor_job(
self.coordinator.ezviz_client.switch_status, self._serial, self._name, 1
)
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 PyEzvizError(f"Failed to turn on switch {self._name}") from err

if update_ok:
await self.coordinator.async_request_refresh()
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:
update_ok = await self.hass.async_add_executor_job(
self.coordinator.ezviz_client.switch_status, self._serial, self._name, 0
)
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 PyEzvizError(f"Failed to turn off switch {self._name}") from err
raise HomeAssistantError(f"Failed to turn off switch {self.name}") from err

if update_ok:
await self.coordinator.async_request_refresh()
@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()

0 comments on commit f52876c

Please sign in to comment.