Home Assistant Unofficial Reference 2024.12.1
valve.py
Go to the documentation of this file.
1 """Valves for the Elexa Guardian integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable, Coroutine
6 from dataclasses import dataclass
7 from enum import StrEnum
8 from typing import Any
9 
10 from aioguardian import Client
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 . import GuardianData
23 from .const import API_VALVE_STATUS, DOMAIN
24 from .entity import ValveControllerEntity, ValveControllerEntityDescription
25 from .util import convert_exceptions_to_homeassistant_error
26 
27 VALVE_KIND_VALVE = "valve"
28 
29 
30 class GuardianValveState(StrEnum):
31  """States of a valve."""
32 
33  CLOSED = "closed"
34  CLOSING = "closing"
35  FINISH_CLOSING = "finish_closing"
36  FINISH_OPENING = "finish_opening"
37  OPEN = "open"
38  OPENING = "opening"
39  START_CLOSING = "start_closing"
40  START_OPENING = "start_opening"
41 
42 
43 @dataclass(frozen=True, kw_only=True)
45  ValveEntityDescription, ValveControllerEntityDescription
46 ):
47  """Describe a Guardian valve controller valve."""
48 
49  is_closed_fn: Callable[[dict[str, Any]], bool]
50  is_closing_fn: Callable[[dict[str, Any]], bool]
51  is_opening_fn: Callable[[dict[str, Any]], bool]
52  close_coro_fn: Callable[[Client], Coroutine[Any, Any, None]]
53  halt_coro_fn: Callable[[Client], Coroutine[Any, Any, None]]
54  open_coro_fn: Callable[[Client], Coroutine[Any, Any, None]]
55 
56 
57 async def async_close_valve(client: Client) -> None:
58  """Close the valve."""
59  async with client:
60  await client.valve.close()
61 
62 
63 async def async_halt_valve(client: Client) -> None:
64  """Halt the valve."""
65  async with client:
66  await client.valve.halt()
67 
68 
69 async def async_open_valve(client: Client) -> None:
70  """Open the valve."""
71  async with client:
72  await client.valve.open()
73 
74 
75 @callback
76 def is_closing(data: dict[str, Any]) -> bool:
77  """Return if the valve is closing."""
78  return data["state"] in (
79  GuardianValveState.CLOSING,
80  GuardianValveState.FINISH_CLOSING,
81  GuardianValveState.START_CLOSING,
82  )
83 
84 
85 @callback
86 def is_opening(data: dict[str, Any]) -> bool:
87  """Return if the valve is opening."""
88  return data["state"] in (
89  GuardianValveState.OPENING,
90  GuardianValveState.FINISH_OPENING,
91  GuardianValveState.START_OPENING,
92  )
93 
94 
95 VALVE_CONTROLLER_DESCRIPTIONS = (
97  key=VALVE_KIND_VALVE,
98  translation_key="valve_controller",
99  device_class=ValveDeviceClass.WATER,
100  api_category=API_VALVE_STATUS,
101  is_closed_fn=lambda data: data["state"] == GuardianValveState.CLOSED,
102  is_closing_fn=is_closing,
103  is_opening_fn=is_opening,
104  close_coro_fn=async_close_valve,
105  halt_coro_fn=async_halt_valve,
106  open_coro_fn=async_open_valve,
107  ),
108 )
109 
110 
112  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
113 ) -> None:
114  """Set up Guardian switches based on a config entry."""
115  data: GuardianData = hass.data[DOMAIN][entry.entry_id]
116 
118  ValveControllerValve(entry, data, description)
119  for description in VALVE_CONTROLLER_DESCRIPTIONS
120  )
121 
122 
124  """Define a switch related to a Guardian valve controller."""
125 
126  _attr_supported_features = (
127  ValveEntityFeature.OPEN | ValveEntityFeature.CLOSE | ValveEntityFeature.STOP
128  )
129  entity_description: ValveControllerValveDescription
130 
131  def __init__(
132  self,
133  entry: ConfigEntry,
134  data: GuardianData,
135  description: ValveControllerValveDescription,
136  ) -> None:
137  """Initialize."""
138  super().__init__(entry, data.valve_controller_coordinators, description)
139 
140  self._client_client_client = data.client
141 
142  @property
143  def is_closing(self) -> bool:
144  """Return if the valve is closing or not."""
145  return self.entity_descriptionentity_description.is_closing_fn(self.coordinator.data)
146 
147  @property
148  def is_closed(self) -> bool:
149  """Return if the valve is closed or not."""
150  return self.entity_descriptionentity_description.is_closed_fn(self.coordinator.data)
151 
152  @property
153  def is_opening(self) -> bool:
154  """Return if the valve is opening or not."""
155  return self.entity_descriptionentity_description.is_opening_fn(self.coordinator.data)
156 
157  @convert_exceptions_to_homeassistant_error
158  async def async_close_valve(self) -> None:
159  """Close the valve."""
160  await self.entity_descriptionentity_description.close_coro_fn(self._client_client_client)
161  await self.coordinator.async_request_refresh()
162 
163  @convert_exceptions_to_homeassistant_error
164  async def async_open_valve(self) -> None:
165  """Open the valve."""
166  await self.entity_descriptionentity_description.open_coro_fn(self._client_client_client)
167  await self.coordinator.async_request_refresh()
168 
169  @convert_exceptions_to_homeassistant_error
170  async def async_stop_valve(self) -> None:
171  """Stop the valve."""
172  await self.entity_descriptionentity_description.halt_coro_fn(self._client_client_client)
173  await self.coordinator.async_request_refresh()
None __init__(self, ConfigEntry entry, GuardianData data, ValveControllerValveDescription description)
Definition: valve.py:136
None async_open_valve(Client client)
Definition: valve.py:69
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: valve.py:113
None async_close_valve(Client client)
Definition: valve.py:57
bool is_opening(dict[str, Any] data)
Definition: valve.py:86
None async_halt_valve(Client client)
Definition: valve.py:63
bool is_closing(dict[str, Any] data)
Definition: valve.py:76