Add image entity (screenshot) in Fully Kiosk Browser (#119622)

This commit is contained in:
tronikos 2024-06-22 10:37:18 -07:00 committed by GitHub
parent 753ab08b5e
commit 725c309c0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 122 additions and 0 deletions

View File

@ -14,6 +14,7 @@ PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.BUTTON,
Platform.CAMERA,
Platform.IMAGE,
Platform.MEDIA_PLAYER,
Platform.NOTIFY,
Platform.NUMBER,

View File

@ -0,0 +1,74 @@
"""Support for Fully Kiosk Browser image."""
from __future__ import annotations
from collections.abc import Callable, Coroutine
from dataclasses import dataclass
from typing import Any
from fullykiosk import FullyKiosk, FullyKioskError
from homeassistant.components.image import ImageEntity, ImageEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
import homeassistant.util.dt as dt_util
from .const import DOMAIN
from .coordinator import FullyKioskDataUpdateCoordinator
from .entity import FullyKioskEntity
@dataclass(frozen=True, kw_only=True)
class FullyImageEntityDescription(ImageEntityDescription):
"""Fully Kiosk Browser image entity description."""
image_fn: Callable[[FullyKiosk], Coroutine[Any, Any, bytes]]
IMAGES: tuple[FullyImageEntityDescription, ...] = (
FullyImageEntityDescription(
key="screenshot",
translation_key="screenshot",
image_fn=lambda fully: fully.getScreenshot(),
),
)
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the Fully Kiosk Browser image entities."""
coordinator: FullyKioskDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
FullyImageEntity(coordinator, description) for description in IMAGES
)
class FullyImageEntity(FullyKioskEntity, ImageEntity):
"""Implement the image entity for Fully Kiosk Browser."""
entity_description: FullyImageEntityDescription
_attr_content_type = "image/png"
def __init__(
self,
coordinator: FullyKioskDataUpdateCoordinator,
description: FullyImageEntityDescription,
) -> None:
"""Initialize the entity."""
FullyKioskEntity.__init__(self, coordinator)
ImageEntity.__init__(self, coordinator.hass)
self.entity_description = description
self._attr_unique_id = f"{coordinator.data['deviceID']}-{description.key}"
async def async_image(self) -> bytes | None:
"""Return bytes of image."""
try:
image_bytes = await self.entity_description.image_fn(self.coordinator.fully)
except FullyKioskError as err:
raise HomeAssistantError(err) from err
else:
self._attr_image_last_updated = dt_util.utcnow()
return image_bytes

View File

@ -56,6 +56,11 @@
"name": "Load start URL"
}
},
"image": {
"screenshot": {
"name": "Screenshot"
}
},
"notify": {
"overlay_message": {
"name": "Overlay message"

View File

@ -0,0 +1,42 @@
"""Test the Fully Kiosk Browser image platform."""
from http import HTTPStatus
from unittest.mock import MagicMock
from fullykiosk import FullyKioskError
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from tests.common import MockConfigEntry
from tests.typing import ClientSessionGenerator
async def test_image(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
hass_client: ClientSessionGenerator,
mock_fully_kiosk: MagicMock,
init_integration: MockConfigEntry,
) -> None:
"""Test the image entity."""
entity_image = "image.amazon_fire_screenshot"
entity = hass.states.get(entity_image)
assert entity
assert entity.state == "unknown"
entry = entity_registry.async_get(entity_image)
assert entry
assert entry.unique_id == "abcdef-123456-screenshot"
mock_fully_kiosk.getScreenshot.return_value = b"image_bytes"
client = await hass_client()
resp = await client.get(f"/api/image_proxy/{entity_image}")
assert resp.status == HTTPStatus.OK
assert resp.headers["Content-Type"] == "image/png"
assert await resp.read() == b"image_bytes"
assert mock_fully_kiosk.getScreenshot.call_count == 1
mock_fully_kiosk.getScreenshot.side_effect = FullyKioskError("error", "status")
client = await hass_client()
resp = await client.get(f"/api/image_proxy/{entity_image}")
assert resp.status == HTTPStatus.INTERNAL_SERVER_ERROR