1 """PrusaLink sensors."""
3 from __future__
import annotations
5 from collections.abc
import Callable, Coroutine
6 from dataclasses
import dataclass
7 from typing
import Any, Generic, TypeVar, cast
9 from pyprusalink
import JobInfo, LegacyPrinterStatus, PrinterStatus, PrusaLink
10 from pyprusalink.types
import Conflict, PrinterState
18 from .const
import DOMAIN
19 from .coordinator
import PrusaLinkUpdateCoordinator
20 from .entity
import PrusaLinkEntity
22 T = TypeVar(
"T", PrinterStatus, LegacyPrinterStatus, JobInfo)
25 @dataclass(frozen=True)
27 """Mixin for required keys."""
29 press_fn: Callable[[PrusaLink], Callable[[int], Coroutine[Any, Any,
None]]]
32 @dataclass(frozen=True)
34 ButtonEntityDescription, PrusaLinkButtonEntityDescriptionMixin[T], Generic[T]
36 """Describes PrusaLink button entity."""
38 available_fn: Callable[[T], bool] =
lambda _:
True
41 BUTTONS: dict[str, tuple[PrusaLinkButtonEntityDescription, ...]] = {
43 PrusaLinkButtonEntityDescription[PrinterStatus](
44 key=
"printer.cancel_job",
45 translation_key=
"cancel_job",
46 press_fn=
lambda api: api.cancel_job,
47 available_fn=
lambda data: (
48 data[
"printer"][
"state"]
49 in [PrinterState.PRINTING.value, PrinterState.PAUSED.value]
52 PrusaLinkButtonEntityDescription[PrinterStatus](
54 translation_key=
"pause_job",
55 press_fn=
lambda api: api.pause_job,
56 available_fn=
lambda data: cast(
57 bool, data[
"printer"][
"state"] == PrinterState.PRINTING.value
60 PrusaLinkButtonEntityDescription[PrinterStatus](
62 translation_key=
"resume_job",
63 press_fn=
lambda api: api.resume_job,
64 available_fn=
lambda data: cast(
65 bool, data[
"printer"][
"state"] == PrinterState.PAUSED.value
75 async_add_entities: AddEntitiesCallback,
77 """Set up PrusaLink buttons based on a config entry."""
78 coordinators: dict[str, PrusaLinkUpdateCoordinator] = hass.data[DOMAIN][
82 entities: list[PrusaLinkEntity] = []
84 for coordinator_type, sensors
in BUTTONS.items():
85 coordinator = coordinators[coordinator_type]
88 for sensor_description
in sensors
95 """Defines a PrusaLink button."""
97 entity_description: PrusaLinkButtonEntityDescription
101 coordinator: PrusaLinkUpdateCoordinator,
102 description: PrusaLinkButtonEntityDescription,
104 """Initialize a PrusaLink sensor entity."""
105 super().
__init__(coordinator=coordinator)
107 self.
_attr_unique_id_attr_unique_id = f
"{coordinator.config_entry.entry_id}_{description.key}"
111 """Return if sensor is available."""
113 self.coordinator.data
117 """Press the button."""
118 job_id = self.coordinator.data[
"job"][
"id"]
122 except Conflict
as err:
124 "Action conflicts with current printer state"
127 coordinators: dict[str, PrusaLinkUpdateCoordinator] = self.
hasshasshass.data[DOMAIN][
128 self.coordinator.config_entry.entry_id
131 for coordinator
in coordinators.values():
132 coordinator.expect_change()
133 await coordinator.async_request_refresh()