Add image platform to Habitica integration (#129009)

pull/134580/head
Manu 2025-01-03 20:23:43 +01:00 committed by GitHub
parent 8a84abd50f
commit 9f2cb7bf56
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 94 additions and 0 deletions

View File

@ -21,6 +21,7 @@ PLATFORMS = [
Platform.BINARY_SENSOR, Platform.BINARY_SENSOR,
Platform.BUTTON, Platform.BUTTON,
Platform.CALENDAR, Platform.CALENDAR,
Platform.IMAGE,
Platform.SENSOR, Platform.SENSOR,
Platform.SWITCH, Platform.SWITCH,
Platform.TODO, Platform.TODO,

View File

@ -5,6 +5,7 @@ from __future__ import annotations
from collections.abc import Callable from collections.abc import Callable
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
from io import BytesIO
import logging import logging
from typing import Any from typing import Any
@ -18,6 +19,7 @@ from habiticalib import (
TaskFilter, TaskFilter,
TooManyRequestsError, TooManyRequestsError,
UserData, UserData,
UserStyles,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -130,3 +132,13 @@ class HabiticaDataUpdateCoordinator(DataUpdateCoordinator[HabiticaData]):
) from e ) from e
else: else:
await self.async_request_refresh() await self.async_request_refresh()
async def generate_avatar(self, user_styles: UserStyles) -> bytes:
"""Generate Avatar."""
avatar = BytesIO()
await self.habitica.generate_avatar(
fp=avatar, user_styles=user_styles, fmt="PNG"
)
return avatar.getvalue()

View File

@ -0,0 +1,76 @@
"""Image platform for Habitica integration."""
from __future__ import annotations
from dataclasses import asdict
from enum import StrEnum
from habiticalib import UserStyles
from homeassistant.components.image import ImageEntity, ImageEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import dt as dt_util
from . import HabiticaConfigEntry
from .coordinator import HabiticaDataUpdateCoordinator
from .entity import HabiticaBase
class HabiticaImageEntity(StrEnum):
"""Image entities."""
AVATAR = "avatar"
async def async_setup_entry(
hass: HomeAssistant,
config_entry: HabiticaConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the habitica image platform."""
coordinator = config_entry.runtime_data
async_add_entities([HabiticaImage(hass, coordinator)])
class HabiticaImage(HabiticaBase, ImageEntity):
"""A Habitica image entity."""
entity_description = ImageEntityDescription(
key=HabiticaImageEntity.AVATAR,
translation_key=HabiticaImageEntity.AVATAR,
)
_attr_content_type = "image/png"
_current_appearance: UserStyles | None = None
_cache: bytes | None = None
def __init__(
self,
hass: HomeAssistant,
coordinator: HabiticaDataUpdateCoordinator,
) -> None:
"""Initialize the image entity."""
super().__init__(coordinator, self.entity_description)
ImageEntity.__init__(self, hass)
self._attr_image_last_updated = dt_util.utcnow()
def _handle_coordinator_update(self) -> None:
"""Check if equipped gear and other things have changed since last avatar image generation."""
new_appearance = UserStyles.from_dict(asdict(self.coordinator.data.user))
if self._current_appearance != new_appearance:
self._current_appearance = new_appearance
self._attr_image_last_updated = dt_util.utcnow()
self._cache = None
return super()._handle_coordinator_update()
async def async_image(self) -> bytes | None:
"""Return cached bytes, otherwise generate new avatar."""
if not self._cache and self._current_appearance:
self._cache = await self.coordinator.generate_avatar(
self._current_appearance
)
return self._cache

View File

@ -167,6 +167,11 @@
"name": "Daily reminders" "name": "Daily reminders"
} }
}, },
"image": {
"avatar": {
"name": "Avatar"
}
},
"sensor": { "sensor": {
"display_name": { "display_name": {
"name": "Display name" "name": "Display name"