diff --git a/.coveragerc b/.coveragerc index c244617007f..e653b35b62d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -327,6 +327,7 @@ omit = homeassistant/components/ezviz/__init__.py homeassistant/components/ezviz/binary_sensor.py homeassistant/components/ezviz/camera.py + homeassistant/components/ezviz/light.py homeassistant/components/ezviz/coordinator.py homeassistant/components/ezviz/number.py homeassistant/components/ezviz/entity.py diff --git a/homeassistant/components/ezviz/__init__.py b/homeassistant/components/ezviz/__init__.py index 2966c339f95..9386a407acb 100644 --- a/homeassistant/components/ezviz/__init__.py +++ b/homeassistant/components/ezviz/__init__.py @@ -35,6 +35,7 @@ PLATFORMS_BY_TYPE: dict[str, list] = { ATTR_TYPE_CLOUD: [ Platform.BINARY_SENSOR, Platform.CAMERA, + Platform.LIGHT, Platform.NUMBER, Platform.SENSOR, Platform.SWITCH, diff --git a/homeassistant/components/ezviz/light.py b/homeassistant/components/ezviz/light.py new file mode 100644 index 00000000000..38007962e4e --- /dev/null +++ b/homeassistant/components/ezviz/light.py @@ -0,0 +1,125 @@ +"""Support for EZVIZ light entity.""" +from __future__ import annotations + +from typing import Any + +from pyezviz.constants import DeviceCatagories, DeviceSwitchType, SupportExt +from pyezviz.exceptions import HTTPError, PyEzvizError + +from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.util.percentage import ( + percentage_to_ranged_value, + ranged_value_to_percentage, +) + +from .const import DATA_COORDINATOR, DOMAIN +from .coordinator import EzvizDataUpdateCoordinator +from .entity import EzvizEntity + +PARALLEL_UPDATES = 1 +BRIGHTNESS_RANGE = (1, 255) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up EZVIZ lights based on a config entry.""" + coordinator: EzvizDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][ + DATA_COORDINATOR + ] + + async_add_entities( + EzvizLight(coordinator, camera) + for camera in coordinator.data + for capibility, value in coordinator.data[camera]["supportExt"].items() + if capibility == str(SupportExt.SupportAlarmLight.value) + if value == "1" + ) + + +class EzvizLight(EzvizEntity, LightEntity): + """Representation of a EZVIZ light.""" + + _attr_has_entity_name = True + _attr_color_mode = ColorMode.BRIGHTNESS + _attr_supported_color_modes = {ColorMode.BRIGHTNESS} + + def __init__( + self, + coordinator: EzvizDataUpdateCoordinator, + serial: str, + ) -> None: + """Initialize the light.""" + super().__init__(coordinator, serial) + self.battery_cam_type = bool( + self.data["device_category"] + == DeviceCatagories.BATTERY_CAMERA_DEVICE_CATEGORY.value + ) + self._attr_unique_id = f"{serial}_Light" + self._attr_name = "Light" + + @property + def brightness(self) -> int | None: + """Return the brightness of this light between 0..255.""" + return round( + percentage_to_ranged_value( + BRIGHTNESS_RANGE, + self.coordinator.data[self._serial]["alarm_light_luminance"], + ) + ) + + @property + def is_on(self) -> bool: + """Return the state of the light.""" + return self.data["switches"][DeviceSwitchType.ALARM_LIGHT.value] + + async def async_turn_on(self, **kwargs: Any) -> None: + """Turn on light.""" + try: + if ATTR_BRIGHTNESS in kwargs: + data = ranged_value_to_percentage( + BRIGHTNESS_RANGE, kwargs[ATTR_BRIGHTNESS] + ) + + update_ok = await self.hass.async_add_executor_job( + self.coordinator.ezviz_client.set_floodlight_brightness, + self._serial, + data, + ) + else: + update_ok = await self.hass.async_add_executor_job( + self.coordinator.ezviz_client.switch_status, + self._serial, + DeviceSwitchType.ALARM_LIGHT.value, + 1, + ) + + except (HTTPError, PyEzvizError) as err: + raise HomeAssistantError( + f"Failed to turn on light {self._attr_name}" + ) from err + + if update_ok: + await self.coordinator.async_request_refresh() + + async def async_turn_off(self, **kwargs: Any) -> None: + """Turn off light.""" + try: + update_ok = await self.hass.async_add_executor_job( + self.coordinator.ezviz_client.switch_status, + self._serial, + DeviceSwitchType.ALARM_LIGHT.value, + 0, + ) + + except (HTTPError, PyEzvizError) as err: + raise HomeAssistantError( + f"Failed to turn off light {self._attr_name}" + ) from err + + if update_ok: + await self.coordinator.async_request_refresh() diff --git a/homeassistant/components/ezviz/manifest.json b/homeassistant/components/ezviz/manifest.json index 219f4c87d13..6697fbce71d 100644 --- a/homeassistant/components/ezviz/manifest.json +++ b/homeassistant/components/ezviz/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/ezviz", "iot_class": "cloud_polling", "loggers": ["paho_mqtt", "pyezviz"], - "requirements": ["pyezviz==0.2.0.12"] + "requirements": ["pyezviz==0.2.0.15"] } diff --git a/requirements_all.txt b/requirements_all.txt index 9ca4b9192a2..ce188858754 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1664,7 +1664,7 @@ pyeverlights==0.1.0 pyevilgenius==2.0.0 # homeassistant.components.ezviz -pyezviz==0.2.0.12 +pyezviz==0.2.0.15 # homeassistant.components.fibaro pyfibaro==0.7.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index ae8f7a56e12..509fe08b37a 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1219,7 +1219,7 @@ pyeverlights==0.1.0 pyevilgenius==2.0.0 # homeassistant.components.ezviz -pyezviz==0.2.0.12 +pyezviz==0.2.0.15 # homeassistant.components.fibaro pyfibaro==0.7.1