mirror of https://github.com/home-assistant/core
100 lines
3.5 KiB
Python
100 lines
3.5 KiB
Python
"""Support EZVIZ last motion image."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
|
|
from pyezviz.exceptions import PyEzvizError
|
|
from pyezviz.utils import decrypt_image
|
|
|
|
from homeassistant.components.image import Image, ImageEntity, ImageEntityDescription
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import CONF_PASSWORD
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
from .const import DATA_COORDINATOR, DOMAIN
|
|
from .coordinator import EzvizDataUpdateCoordinator
|
|
from .entity import EzvizEntity
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
IMAGE_TYPE = ImageEntityDescription(
|
|
key="last_motion_image",
|
|
translation_key="last_motion_image",
|
|
)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
|
) -> None:
|
|
"""Set up EZVIZ image entities based on a config entry."""
|
|
|
|
coordinator: EzvizDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][
|
|
DATA_COORDINATOR
|
|
]
|
|
|
|
async_add_entities(
|
|
EzvizLastMotion(hass, coordinator, camera) for camera in coordinator.data
|
|
)
|
|
|
|
|
|
class EzvizLastMotion(EzvizEntity, ImageEntity):
|
|
"""Return Last Motion Image from Ezviz Camera."""
|
|
|
|
def __init__(
|
|
self, hass: HomeAssistant, coordinator: EzvizDataUpdateCoordinator, serial: str
|
|
) -> None:
|
|
"""Initialize a image entity."""
|
|
EzvizEntity.__init__(self, coordinator, serial)
|
|
ImageEntity.__init__(self, hass)
|
|
self._attr_unique_id = f"{serial}_{IMAGE_TYPE.key}"
|
|
self.entity_description = IMAGE_TYPE
|
|
self._attr_image_url = self.data["last_alarm_pic"]
|
|
self._attr_image_last_updated = dt_util.parse_datetime(
|
|
str(self.data["last_alarm_time"])
|
|
)
|
|
camera = hass.config_entries.async_entry_for_domain_unique_id(DOMAIN, serial)
|
|
self.alarm_image_password = (
|
|
camera.data[CONF_PASSWORD] if camera is not None else None
|
|
)
|
|
|
|
async def _async_load_image_from_url(self, url: str) -> Image | None:
|
|
"""Load an image by url."""
|
|
if response := await self._fetch_url(url):
|
|
image_data = response.content
|
|
if self.data["encrypted"] and self.alarm_image_password is not None:
|
|
try:
|
|
image_data = decrypt_image(
|
|
response.content, self.alarm_image_password
|
|
)
|
|
except PyEzvizError:
|
|
_LOGGER.warning(
|
|
"%s: Can't decrypt last alarm picture, looks like it was encrypted with other password",
|
|
self.entity_id,
|
|
)
|
|
image_data = response.content
|
|
return Image(
|
|
content=image_data,
|
|
content_type="image/jpeg", # Actually returns binary/octet-stream
|
|
)
|
|
return None
|
|
|
|
@callback
|
|
def _handle_coordinator_update(self) -> None:
|
|
"""Handle updated data from the coordinator."""
|
|
if (
|
|
self.data["last_alarm_pic"]
|
|
and self.data["last_alarm_pic"] != self._attr_image_url
|
|
):
|
|
_LOGGER.debug("Image url changed to %s", self.data["last_alarm_pic"])
|
|
|
|
self._attr_image_url = self.data["last_alarm_pic"]
|
|
self._cached_image = None
|
|
self._attr_image_last_updated = dt_util.parse_datetime(
|
|
str(self.data["last_alarm_time"])
|
|
)
|
|
|
|
super()._handle_coordinator_update()
|