Home Assistant Unofficial Reference 2024.12.1
number.py
Go to the documentation of this file.
1 """Number platform for La Marzocco espresso machines."""
2 
3 from collections.abc import Callable, Coroutine
4 from dataclasses import dataclass
5 from typing import Any
6 
7 from pylamarzocco.const import (
8  KEYS_PER_MODEL,
9  BoilerType,
10  MachineModel,
11  PhysicalKey,
12  PrebrewMode,
13 )
14 from pylamarzocco.exceptions import RequestNotSuccessful
15 from pylamarzocco.lm_machine import LaMarzoccoMachine
16 from pylamarzocco.models import LaMarzoccoMachineConfig
17 
19  NumberDeviceClass,
20  NumberEntity,
21  NumberEntityDescription,
22 )
23 from homeassistant.const import (
24  PRECISION_TENTHS,
25  PRECISION_WHOLE,
26  EntityCategory,
27  UnitOfTemperature,
28  UnitOfTime,
29 )
30 from homeassistant.core import HomeAssistant
31 from homeassistant.exceptions import HomeAssistantError
32 from homeassistant.helpers.entity_platform import AddEntitiesCallback
33 
34 from .const import DOMAIN
35 from .coordinator import LaMarzoccoConfigEntry, LaMarzoccoUpdateCoordinator
36 from .entity import LaMarzoccoEntity, LaMarzoccoEntityDescription
37 
38 PARALLEL_UPDATES = 1
39 
40 
41 @dataclass(frozen=True, kw_only=True)
43  LaMarzoccoEntityDescription,
44  NumberEntityDescription,
45 ):
46  """Description of a La Marzocco number entity."""
47 
48  native_value_fn: Callable[[LaMarzoccoMachineConfig], float | int]
49  set_value_fn: Callable[[LaMarzoccoMachine, float | int], Coroutine[Any, Any, bool]]
50 
51 
52 @dataclass(frozen=True, kw_only=True)
54  LaMarzoccoEntityDescription,
55  NumberEntityDescription,
56 ):
57  """Description of an La Marzocco number entity with keys."""
58 
59  native_value_fn: Callable[[LaMarzoccoMachineConfig, PhysicalKey], float | int]
60  set_value_fn: Callable[
61  [LaMarzoccoMachine, float | int, PhysicalKey], Coroutine[Any, Any, bool]
62  ]
63 
64 
65 ENTITIES: tuple[LaMarzoccoNumberEntityDescription, ...] = (
67  key="coffee_temp",
68  translation_key="coffee_temp",
69  device_class=NumberDeviceClass.TEMPERATURE,
70  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
71  native_step=PRECISION_TENTHS,
72  native_min_value=85,
73  native_max_value=104,
74  set_value_fn=lambda machine, temp: machine.set_temp(BoilerType.COFFEE, temp),
75  native_value_fn=lambda config: config.boilers[
76  BoilerType.COFFEE
77  ].target_temperature,
78  ),
80  key="steam_temp",
81  translation_key="steam_temp",
82  device_class=NumberDeviceClass.TEMPERATURE,
83  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
84  native_step=PRECISION_WHOLE,
85  native_min_value=126,
86  native_max_value=131,
87  set_value_fn=lambda machine, temp: machine.set_temp(BoilerType.STEAM, temp),
88  native_value_fn=lambda config: config.boilers[
89  BoilerType.STEAM
90  ].target_temperature,
91  supported_fn=lambda coordinator: coordinator.device.model
92  in (
93  MachineModel.GS3_AV,
94  MachineModel.GS3_MP,
95  ),
96  ),
98  key="tea_water_duration",
99  translation_key="tea_water_duration",
100  device_class=NumberDeviceClass.DURATION,
101  native_unit_of_measurement=UnitOfTime.SECONDS,
102  native_step=PRECISION_WHOLE,
103  native_min_value=0,
104  native_max_value=30,
105  set_value_fn=lambda machine, value: machine.set_dose_tea_water(int(value)),
106  native_value_fn=lambda config: config.dose_hot_water,
107  supported_fn=lambda coordinator: coordinator.device.model
108  in (
109  MachineModel.GS3_AV,
110  MachineModel.GS3_MP,
111  ),
112  ),
114  key="smart_standby_time",
115  translation_key="smart_standby_time",
116  device_class=NumberDeviceClass.DURATION,
117  native_unit_of_measurement=UnitOfTime.MINUTES,
118  native_step=10,
119  native_min_value=10,
120  native_max_value=240,
121  entity_category=EntityCategory.CONFIG,
122  set_value_fn=lambda machine, value: machine.set_smart_standby(
123  enabled=machine.config.smart_standby.enabled,
124  mode=machine.config.smart_standby.mode,
125  minutes=int(value),
126  ),
127  native_value_fn=lambda config: config.smart_standby.minutes,
128  ),
129 )
130 
131 
132 KEY_ENTITIES: tuple[LaMarzoccoKeyNumberEntityDescription, ...] = (
134  key="prebrew_off",
135  translation_key="prebrew_off",
136  device_class=NumberDeviceClass.DURATION,
137  native_unit_of_measurement=UnitOfTime.SECONDS,
138  native_step=PRECISION_TENTHS,
139  native_min_value=1,
140  native_max_value=10,
141  entity_category=EntityCategory.CONFIG,
142  set_value_fn=lambda machine, value, key: machine.set_prebrew_time(
143  prebrew_off_time=value, key=key
144  ),
145  native_value_fn=lambda config, key: config.prebrew_configuration[key].off_time,
146  available_fn=lambda device: len(device.config.prebrew_configuration) > 0
147  and device.config.prebrew_mode == PrebrewMode.PREBREW,
148  supported_fn=lambda coordinator: coordinator.device.model
149  != MachineModel.GS3_MP,
150  ),
152  key="prebrew_on",
153  translation_key="prebrew_on",
154  device_class=NumberDeviceClass.DURATION,
155  native_unit_of_measurement=UnitOfTime.SECONDS,
156  native_step=PRECISION_TENTHS,
157  native_min_value=2,
158  native_max_value=10,
159  entity_category=EntityCategory.CONFIG,
160  set_value_fn=lambda machine, value, key: machine.set_prebrew_time(
161  prebrew_on_time=value, key=key
162  ),
163  native_value_fn=lambda config, key: config.prebrew_configuration[key].off_time,
164  available_fn=lambda device: len(device.config.prebrew_configuration) > 0
165  and device.config.prebrew_mode == PrebrewMode.PREBREW,
166  supported_fn=lambda coordinator: coordinator.device.model
167  != MachineModel.GS3_MP,
168  ),
170  key="preinfusion_off",
171  translation_key="preinfusion_off",
172  device_class=NumberDeviceClass.DURATION,
173  native_unit_of_measurement=UnitOfTime.SECONDS,
174  native_step=PRECISION_TENTHS,
175  native_min_value=2,
176  native_max_value=29,
177  entity_category=EntityCategory.CONFIG,
178  set_value_fn=lambda machine, value, key: machine.set_preinfusion_time(
179  preinfusion_time=value, key=key
180  ),
181  native_value_fn=lambda config, key: config.prebrew_configuration[
182  key
183  ].preinfusion_time,
184  available_fn=lambda device: len(device.config.prebrew_configuration) > 0
185  and device.config.prebrew_mode == PrebrewMode.PREINFUSION,
186  supported_fn=lambda coordinator: coordinator.device.model
187  != MachineModel.GS3_MP,
188  ),
190  key="dose",
191  translation_key="dose",
192  native_unit_of_measurement="ticks",
193  native_step=PRECISION_WHOLE,
194  native_min_value=0,
195  native_max_value=999,
196  entity_category=EntityCategory.CONFIG,
197  set_value_fn=lambda machine, ticks, key: machine.set_dose(
198  dose=int(ticks), key=key
199  ),
200  native_value_fn=lambda config, key: config.doses[key],
201  supported_fn=lambda coordinator: coordinator.device.model
202  == MachineModel.GS3_AV,
203  ),
204 )
205 
206 
208  hass: HomeAssistant,
209  entry: LaMarzoccoConfigEntry,
210  async_add_entities: AddEntitiesCallback,
211 ) -> None:
212  """Set up number entities."""
213  coordinator = entry.runtime_data
214  entities: list[NumberEntity] = [
215  LaMarzoccoNumberEntity(coordinator, description)
216  for description in ENTITIES
217  if description.supported_fn(coordinator)
218  ]
219 
220  for description in KEY_ENTITIES:
221  if description.supported_fn(coordinator):
222  num_keys = KEYS_PER_MODEL[MachineModel(coordinator.device.model)]
223  entities.extend(
224  LaMarzoccoKeyNumberEntity(coordinator, description, key)
225  for key in range(min(num_keys, 1), num_keys + 1)
226  )
227  async_add_entities(entities)
228 
229 
231  """La Marzocco number entity."""
232 
233  entity_description: LaMarzoccoNumberEntityDescription
234 
235  @property
236  def native_value(self) -> float:
237  """Return the current value."""
238  return self.entity_descriptionentity_description.native_value_fn(self.coordinator.device.config)
239 
240  async def async_set_native_value(self, value: float) -> None:
241  """Set the value."""
242  if value != self.native_valuenative_valuenative_value:
243  try:
244  await self.entity_descriptionentity_description.set_value_fn(
245  self.coordinator.device, value
246  )
247  except RequestNotSuccessful as exc:
248  raise HomeAssistantError(
249  translation_domain=DOMAIN,
250  translation_key="number_exception",
251  translation_placeholders={
252  "key": self.entity_descriptionentity_description.key,
253  "value": str(value),
254  },
255  ) from exc
256  self.async_write_ha_stateasync_write_ha_state()
257 
258 
260  """Number representing espresso machine with key support."""
261 
262  entity_description: LaMarzoccoKeyNumberEntityDescription
263 
264  def __init__(
265  self,
266  coordinator: LaMarzoccoUpdateCoordinator,
267  description: LaMarzoccoKeyNumberEntityDescription,
268  pyhsical_key: int,
269  ) -> None:
270  """Initialize the entity."""
271  super().__init__(coordinator, description)
272 
273  # Physical Key on the machine the entity represents.
274  if pyhsical_key == 0:
275  pyhsical_key = 1
276  else:
277  self._attr_translation_key_attr_translation_key = f"{description.translation_key}_key"
278  self._attr_translation_placeholders_attr_translation_placeholders = {"key": str(pyhsical_key)}
279  self._attr_unique_id_attr_unique_id_attr_unique_id = f"{super()._attr_unique_id}_key{pyhsical_key}"
280  self._attr_entity_registry_enabled_default_attr_entity_registry_enabled_default = False
281  self.pyhsical_keypyhsical_key = pyhsical_key
282 
283  @property
284  def native_value(self) -> float:
285  """Return the current value."""
286  return self.entity_descriptionentity_description.native_value_fn(
287  self.coordinator.device.config, PhysicalKey(self.pyhsical_keypyhsical_key)
288  )
289 
290  async def async_set_native_value(self, value: float) -> None:
291  """Set the value."""
292  if value != self.native_valuenative_valuenative_value:
293  try:
294  await self.entity_descriptionentity_description.set_value_fn(
295  self.coordinator.device, value, PhysicalKey(self.pyhsical_keypyhsical_key)
296  )
297  except RequestNotSuccessful as exc:
298  raise HomeAssistantError(
299  translation_domain=DOMAIN,
300  translation_key="number_exception_key",
301  translation_placeholders={
302  "key": self.entity_descriptionentity_description.key,
303  "value": str(value),
304  "physical_key": str(self.pyhsical_keypyhsical_key),
305  },
306  ) from exc
307  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, LaMarzoccoUpdateCoordinator coordinator, LaMarzoccoKeyNumberEntityDescription description, int pyhsical_key)
Definition: number.py:269
None async_setup_entry(HomeAssistant hass, LaMarzoccoConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: number.py:211