Home Assistant Unofficial Reference 2024.12.1
valve.py
Go to the documentation of this file.
1 """YoLink Valve."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 
8 from yolink.client_request import ClientRequest
9 from yolink.const import ATTR_DEVICE_WATER_METER_CONTROLLER
10 from yolink.device import YoLinkDevice
11 
13  ValveDeviceClass,
14  ValveEntity,
15  ValveEntityDescription,
16  ValveEntityFeature,
17 )
18 from homeassistant.config_entries import ConfigEntry
19 from homeassistant.core import HomeAssistant, callback
20 from homeassistant.helpers.entity_platform import AddEntitiesCallback
21 
22 from .const import DEV_MODEL_WATER_METER_YS5007, DOMAIN
23 from .coordinator import YoLinkCoordinator
24 from .entity import YoLinkEntity
25 
26 
27 @dataclass(frozen=True)
29  """YoLink ValveEntityDescription."""
30 
31  exists_fn: Callable[[YoLinkDevice], bool] = lambda _: True
32  value: Callable = lambda state: state
33 
34 
35 DEVICE_TYPES: tuple[YoLinkValveEntityDescription, ...] = (
37  key="valve_state",
38  translation_key="meter_valve_state",
39  device_class=ValveDeviceClass.WATER,
40  value=lambda value: value != "open" if value is not None else None,
41  exists_fn=lambda device: device.device_type
42  == ATTR_DEVICE_WATER_METER_CONTROLLER
43  and not device.device_model_name.startswith(DEV_MODEL_WATER_METER_YS5007),
44  ),
45 )
46 
47 DEVICE_TYPE = [ATTR_DEVICE_WATER_METER_CONTROLLER]
48 
49 
51  hass: HomeAssistant,
52  config_entry: ConfigEntry,
53  async_add_entities: AddEntitiesCallback,
54 ) -> None:
55  """Set up YoLink valve from a config entry."""
56  device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
57  valve_device_coordinators = [
58  device_coordinator
59  for device_coordinator in device_coordinators.values()
60  if device_coordinator.device.device_type in DEVICE_TYPE
61  ]
63  YoLinkValveEntity(config_entry, valve_device_coordinator, description)
64  for valve_device_coordinator in valve_device_coordinators
65  for description in DEVICE_TYPES
66  if description.exists_fn(valve_device_coordinator.device)
67  )
68 
69 
71  """YoLink Valve Entity."""
72 
73  entity_description: YoLinkValveEntityDescription
74 
75  def __init__(
76  self,
77  config_entry: ConfigEntry,
78  coordinator: YoLinkCoordinator,
79  description: YoLinkValveEntityDescription,
80  ) -> None:
81  """Init YoLink valve."""
82  super().__init__(config_entry, coordinator)
83  self._attr_supported_features_attr_supported_features = (
84  ValveEntityFeature.OPEN | ValveEntityFeature.CLOSE
85  )
86  self.entity_descriptionentity_description = description
87  self._attr_unique_id_attr_unique_id = (
88  f"{coordinator.device.device_id} {self.entity_description.key}"
89  )
90 
91  @callback
92  def update_entity_state(self, state: dict[str, str | list[str]]) -> None:
93  """Update HA Entity State."""
94  if (
95  attr_val := self.entity_descriptionentity_description.value(
96  state.get(self.entity_descriptionentity_description.key)
97  )
98  ) is None:
99  return
100  self._attr_is_closed_attr_is_closed = attr_val
101  self.async_write_ha_stateasync_write_ha_state()
102 
103  async def _async_invoke_device(self, state: str) -> None:
104  """Call setState api to change valve state."""
105  await self.call_devicecall_device(ClientRequest("setState", {"valve": state}))
106  self._attr_is_closed_attr_is_closed = state == "close"
107  self.async_write_ha_stateasync_write_ha_state()
108 
109  async def async_open_valve(self) -> None:
110  """Open the valve."""
111  await self._async_invoke_device_async_invoke_device("open")
112 
113  async def async_close_valve(self) -> None:
114  """Close valve."""
115  await self._async_invoke_device_async_invoke_device("close")