Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 4 additions & 11 deletions homeassistant/components/prusalink/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,20 @@
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import PrusaLinkConfigEntry, PrusaLinkUpdateCoordinator
from .entity import PrusaLinkEntity
from .entity import PrusaLinkEntity, PrusaLinkEntityDescription

T = TypeVar("T", PrinterStatus, LegacyPrinterStatus, JobInfo, PrinterInfo)


@dataclass(frozen=True)
class PrusaLinkBinarySensorEntityDescriptionMixin(Generic[T]):
"""Mixin for required keys."""

value_fn: Callable[[T], bool]


@dataclass(frozen=True)
@dataclass(frozen=True, kw_only=True)
class PrusaLinkBinarySensorEntityDescription(
BinarySensorEntityDescription,
PrusaLinkBinarySensorEntityDescriptionMixin[T],
PrusaLinkEntityDescription,
Generic[T],
):
"""Describes PrusaLink sensor entity."""

available_fn: Callable[[T], bool] = lambda _: True
value_fn: Callable[[T], bool]


BINARY_SENSORS: dict[str, tuple[PrusaLinkBinarySensorEntityDescription, ...]] = {
Expand Down
24 changes: 6 additions & 18 deletions homeassistant/components/prusalink/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,20 @@
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import PrusaLinkConfigEntry, PrusaLinkUpdateCoordinator
from .entity import PrusaLinkEntity
from .entity import PrusaLinkEntity, PrusaLinkEntityDescription

T = TypeVar("T", PrinterStatus, LegacyPrinterStatus, JobInfo)


@dataclass(frozen=True)
class PrusaLinkButtonEntityDescriptionMixin(Generic[T]):
"""Mixin for required keys."""

press_fn: Callable[[PrusaLink], Callable[[int], Coroutine[Any, Any, None]]]


@dataclass(frozen=True)
@dataclass(frozen=True, kw_only=True)
class PrusaLinkButtonEntityDescription(
ButtonEntityDescription, PrusaLinkButtonEntityDescriptionMixin[T], Generic[T]
ButtonEntityDescription,
PrusaLinkEntityDescription,
Generic[T],
):
"""Describes PrusaLink button entity."""

available_fn: Callable[[T], bool] = lambda _: True
press_fn: Callable[[PrusaLink], Callable[[int], Coroutine[Any, Any, None]]]


BUTTONS: dict[str, tuple[PrusaLinkButtonEntityDescription, ...]] = {
Expand Down Expand Up @@ -100,13 +95,6 @@ def __init__(
self.entity_description = description
self._attr_unique_id = f"{coordinator.config_entry.entry_id}_{description.key}"

@property
def available(self) -> bool:
"""Return if sensor is available."""
return super().available and self.entity_description.available_fn(
self.coordinator.data
)

async def async_press(self) -> None:
"""Press the button."""
job_id = self.coordinator.data["job"]["id"]
Expand Down
33 changes: 20 additions & 13 deletions homeassistant/components/prusalink/camera.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
"""Camera entity for PrusaLink."""

from dataclasses import dataclass

from pyprusalink.types import PrinterState

from homeassistant.components.camera import Camera
from homeassistant.components.camera import Camera, CameraEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback

from .coordinator import PrusaLinkConfigEntry, PrusaLinkUpdateCoordinator
from .entity import PrusaLinkEntity
from .entity import PrusaLinkEntity, PrusaLinkEntityDescription


@dataclass(frozen=True, kw_only=True)
class PrusaLinkCameraEntityDescription(
CameraEntityDescription, PrusaLinkEntityDescription
):
"""Describes PrusaLink camera entity."""


async def async_setup_entry(
Expand All @@ -23,26 +32,24 @@ async def async_setup_entry(
class PrusaLinkJobPreviewEntity(PrusaLinkEntity, Camera):
"""Defines a PrusaLink camera."""

entity_description = PrusaLinkCameraEntityDescription(
key="job_preview",
translation_key="job_preview",
available_fn=lambda data: bool(
data.get("state") != PrinterState.IDLE.value
and (file := data.get("file"))
and file.get("refs", {}).get("thumbnail")
),
)
last_path = ""
last_image: bytes
_attr_translation_key = "job_preview"

def __init__(self, coordinator: PrusaLinkUpdateCoordinator) -> None:
"""Initialize a PrusaLink camera entity."""
super().__init__(coordinator)
Camera.__init__(self)
self._attr_unique_id = f"{self.coordinator.config_entry.entry_id}_job_preview"

@property
def available(self) -> bool:
"""Get if camera is available."""
return (
super().available
and self.coordinator.data.get("state") != PrinterState.IDLE.value
and (file := self.coordinator.data.get("file"))
and file.get("refs", {}).get("thumbnail")
)

async def async_camera_image(
self, width: int | None = None, height: int | None = None
) -> bytes | None:
Expand Down
21 changes: 21 additions & 0 deletions homeassistant/components/prusalink/entity.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
"""The PrusaLink integration."""

from collections.abc import Callable
from dataclasses import dataclass
from typing import Any

from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN
from .coordinator import PrusaLinkUpdateCoordinator


@dataclass(frozen=True, kw_only=True)
class PrusaLinkEntityDescription(EntityDescription):
"""Base description for PrusaLink entities."""

available_fn: Callable[[Any], bool] = lambda _: True
supported_fn: Callable[[Any], bool] = lambda _: True


class PrusaLinkEntity(CoordinatorEntity[PrusaLinkUpdateCoordinator]):
"""Defines a base PrusaLink entity."""

_attr_has_entity_name = True
entity_description: PrusaLinkEntityDescription

@property
def available(self) -> bool:
"""Return if entity is available."""
return super().available and self.entity_description.available_fn(
self.coordinator.data
)

@property
def device_info(self) -> DeviceInfo:
Expand Down
25 changes: 6 additions & 19 deletions homeassistant/components/prusalink/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,20 @@
from homeassistant.util.variance import ignore_variance

from .coordinator import PrusaLinkConfigEntry, PrusaLinkUpdateCoordinator
from .entity import PrusaLinkEntity
from .entity import PrusaLinkEntity, PrusaLinkEntityDescription

T = TypeVar("T", PrinterStatus, LegacyPrinterStatus, JobInfo, PrinterInfo)


@dataclass(frozen=True)
class PrusaLinkSensorEntityDescriptionMixin(Generic[T]):
"""Mixin for required keys."""

value_fn: Callable[[T], datetime | StateType]


@dataclass(frozen=True)
@dataclass(frozen=True, kw_only=True)
class PrusaLinkSensorEntityDescription(
SensorEntityDescription, PrusaLinkSensorEntityDescriptionMixin[T], Generic[T]
SensorEntityDescription,
PrusaLinkEntityDescription,
Generic[T],
):
"""Describes PrusaLink sensor entity."""

available_fn: Callable[[T], bool] = lambda _: True
supported_fn: Callable[[T], bool] = lambda _: True
value_fn: Callable[[T], datetime | StateType]


SENSORS: dict[str, tuple[PrusaLinkSensorEntityDescription, ...]] = {
Expand Down Expand Up @@ -275,10 +269,3 @@ def __init__(
def native_value(self) -> datetime | StateType:
"""Return the state of the sensor."""
return self.entity_description.value_fn(self.coordinator.data)

@property
def available(self) -> bool:
"""Return if sensor is available."""
return super().available and self.entity_description.available_fn(
self.coordinator.data
)
Loading