Add entity description to EZVIZ SwitchEntity (#95672)

* 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
This commit is contained in:
Renier Moorcroft 2023-07-29 17:37:40 +02:00 committed by GitHub
parent 750260b266
commit f52876c7f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 173 additions and 34 deletions

View file

@ -163,6 +163,44 @@
"last_alarm_type_name": { "last_alarm_type_name": {
"name": "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": { "services": {

View file

@ -1,14 +1,20 @@
"""Support for EZVIZ Switch sensors.""" """Support for EZVIZ Switch sensors."""
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass
from typing import Any from typing import Any
from pyezviz.constants import DeviceSwitchType from pyezviz.constants import DeviceSwitchType, SupportExt
from pyezviz.exceptions import HTTPError, PyEzvizError 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.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 homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DATA_COORDINATOR, DOMAIN from .const import DATA_COORDINATOR, DOMAIN
@ -16,6 +22,96 @@ from .coordinator import EzvizDataUpdateCoordinator
from .entity import EzvizEntity 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( async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None: ) -> None:
@ -24,61 +120,66 @@ async def async_setup_entry(
DATA_COORDINATOR DATA_COORDINATOR
] ]
supported_switches = {switches.value for switches in DeviceSwitchType}
async_add_entities( async_add_entities(
[ EzvizSwitch(coordinator, camera, switch_number)
EzvizSwitch(coordinator, camera, switch)
for camera in coordinator.data for camera in coordinator.data
for switch in coordinator.data[camera].get("switches") for switch_number in coordinator.data[camera]["switches"]
if switch in supported_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): class EzvizSwitch(EzvizEntity, SwitchEntity):
"""Representation of a EZVIZ sensor.""" """Representation of a EZVIZ sensor."""
_attr_device_class = SwitchDeviceClass.SWITCH _attr_has_entity_name = True
def __init__( def __init__(
self, coordinator: EzvizDataUpdateCoordinator, serial: str, switch: str self, coordinator: EzvizDataUpdateCoordinator, serial: str, switch_number: int
) -> None: ) -> None:
"""Initialize the switch.""" """Initialize the switch."""
super().__init__(coordinator, serial) super().__init__(coordinator, serial)
self._name = switch self._switch_number = switch_number
self._attr_name = f"{self._camera_name} {DeviceSwitchType(switch).name.title()}"
self._attr_unique_id = ( self._attr_unique_id = (
f"{serial}_{self._camera_name}.{DeviceSwitchType(switch).name}" f"{serial}_{self._camera_name}.{DeviceSwitchType(switch_number).name}"
) )
self.entity_description = SWITCH_TYPES[switch_number]
@property self._attr_is_on = self.data["switches"][switch_number]
def is_on(self) -> bool:
"""Return the state of the switch."""
return self.data["switches"][self._name]
async def async_turn_on(self, **kwargs: Any) -> None: async def async_turn_on(self, **kwargs: Any) -> None:
"""Change a device switch on the camera.""" """Change a device switch on the camera."""
try: try:
update_ok = await self.hass.async_add_executor_job( if await self.hass.async_add_executor_job(
self.coordinator.ezviz_client.switch_status, self._serial, self._name, 1 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: except (HTTPError, PyEzvizError) as err:
raise PyEzvizError(f"Failed to turn on switch {self._name}") from err raise HomeAssistantError(f"Failed to turn on switch {self.name}") from err
if update_ok:
await self.coordinator.async_request_refresh()
async def async_turn_off(self, **kwargs: Any) -> None: async def async_turn_off(self, **kwargs: Any) -> None:
"""Change a device switch on the camera.""" """Change a device switch on the camera."""
try: try:
update_ok = await self.hass.async_add_executor_job( if await self.hass.async_add_executor_job(
self.coordinator.ezviz_client.switch_status, self._serial, self._name, 0 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: 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: @callback
await self.coordinator.async_request_refresh() 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()