Home Assistant Unofficial Reference 2024.12.1
climate.py
Go to the documentation of this file.
1 """Code to handle a Livisi Virtual Climate Control."""
2 
3 from __future__ import annotations
4 
5 from typing import Any
6 
7 from aiolivisi.const import CAPABILITY_CONFIG
8 
10  ClimateEntity,
11  ClimateEntityFeature,
12  HVACMode,
13 )
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
16 from homeassistant.core import HomeAssistant, callback
17 from homeassistant.exceptions import HomeAssistantError
18 from homeassistant.helpers.dispatcher import async_dispatcher_connect
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 
21 from .const import (
22  DOMAIN,
23  LIVISI_STATE_CHANGE,
24  LOGGER,
25  MAX_TEMPERATURE,
26  MIN_TEMPERATURE,
27  VRCC_DEVICE_TYPE,
28 )
29 from .coordinator import LivisiDataUpdateCoordinator
30 from .entity import LivisiEntity
31 
32 
34  hass: HomeAssistant,
35  config_entry: ConfigEntry,
36  async_add_entities: AddEntitiesCallback,
37 ) -> None:
38  """Set up climate device."""
39  coordinator: LivisiDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
40 
41  @callback
42  def handle_coordinator_update() -> None:
43  """Add climate device."""
44  shc_devices: list[dict[str, Any]] = coordinator.data
45  entities: list[ClimateEntity] = []
46  for device in shc_devices:
47  if (
48  device["type"] == VRCC_DEVICE_TYPE
49  and device["id"] not in coordinator.devices
50  ):
51  livisi_climate: ClimateEntity = LivisiClimate(
52  config_entry, coordinator, device
53  )
54  LOGGER.debug("Include device type: %s", device.get("type"))
55  coordinator.devices.add(device["id"])
56  entities.append(livisi_climate)
57  async_add_entities(entities)
58 
59  config_entry.async_on_unload(
60  coordinator.async_add_listener(handle_coordinator_update)
61  )
62 
63 
65  """Represents the Livisi Climate."""
66 
67  _attr_hvac_modes = [HVACMode.HEAT]
68  _attr_hvac_mode = HVACMode.HEAT
69  _attr_temperature_unit = UnitOfTemperature.CELSIUS
70  _attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
71  _enable_turn_on_off_backwards_compatibility = False
72 
73  def __init__(
74  self,
75  config_entry: ConfigEntry,
76  coordinator: LivisiDataUpdateCoordinator,
77  device: dict[str, Any],
78  ) -> None:
79  """Initialize the Livisi Climate."""
80  super().__init__(
81  config_entry, coordinator, device, use_room_as_device_name=True
82  )
83 
84  self._target_temperature_capability_target_temperature_capability = self.capabilities["RoomSetpoint"]
85  self._temperature_capability_temperature_capability = self.capabilities["RoomTemperature"]
86  self._humidity_capability_humidity_capability = self.capabilities["RoomHumidity"]
87 
88  config = device.get(CAPABILITY_CONFIG, {}).get("RoomSetpoint", {})
89  self._attr_max_temp_attr_max_temp = config.get("maxTemperature", MAX_TEMPERATURE)
90  self._attr_min_temp_attr_min_temp = config.get("minTemperature", MIN_TEMPERATURE)
91 
92  async def async_set_temperature(self, **kwargs: Any) -> None:
93  """Set new target temperature."""
94  response = await self.aio_livisiaio_livisi.async_vrcc_set_temperature(
95  self._target_temperature_capability_target_temperature_capability,
96  kwargs.get(ATTR_TEMPERATURE),
97  self.coordinator.is_avatar,
98  )
99  if response is None:
100  self._attr_available_attr_available_attr_available = False
101  raise HomeAssistantError(f"Failed to turn off {self._attr_name}")
102 
103  async def async_added_to_hass(self) -> None:
104  """Register callbacks."""
105 
106  await super().async_added_to_hass()
107 
108  target_temperature = await self.coordinator.async_get_device_state(
109  self._target_temperature_capability_target_temperature_capability,
110  "setpointTemperature" if self.coordinator.is_avatar else "pointTemperature",
111  )
112  temperature = await self.coordinator.async_get_device_state(
113  self._temperature_capability_temperature_capability, "temperature"
114  )
115  humidity = await self.coordinator.async_get_device_state(
116  self._humidity_capability_humidity_capability, "humidity"
117  )
118  if temperature is None:
119  self._attr_current_temperature_attr_current_temperature = None
120  self._attr_available_attr_available_attr_available = False
121  else:
122  self._attr_target_temperature_attr_target_temperature = target_temperature
123  self._attr_current_temperature_attr_current_temperature = temperature
124  self._attr_current_humidity_attr_current_humidity = humidity
125  self.async_on_removeasync_on_remove(
127  self.hasshasshasshass,
128  f"{LIVISI_STATE_CHANGE}_{self._target_temperature_capability}",
129  self.update_target_temperatureupdate_target_temperature,
130  )
131  )
132  self.async_on_removeasync_on_remove(
134  self.hasshasshasshass,
135  f"{LIVISI_STATE_CHANGE}_{self._temperature_capability}",
136  self.update_temperatureupdate_temperature,
137  )
138  )
139  self.async_on_removeasync_on_remove(
141  self.hasshasshasshass,
142  f"{LIVISI_STATE_CHANGE}_{self._humidity_capability}",
143  self.update_humidityupdate_humidity,
144  )
145  )
146 
147  def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
148  """Do nothing as LIVISI devices do not support changing the hvac mode."""
149 
150  @callback
151  def update_target_temperature(self, target_temperature: float) -> None:
152  """Update the target temperature of the climate device."""
153  self._attr_target_temperature_attr_target_temperature = target_temperature
154  self.async_write_ha_stateasync_write_ha_state()
155 
156  @callback
157  def update_temperature(self, current_temperature: float) -> None:
158  """Update the current temperature of the climate device."""
159  self._attr_current_temperature_attr_current_temperature = current_temperature
160  self.async_write_ha_stateasync_write_ha_state()
161 
162  @callback
163  def update_humidity(self, humidity: int) -> None:
164  """Update the humidity of the climate device."""
165  self._attr_current_humidity_attr_current_humidity = humidity
166  self.async_write_ha_stateasync_write_ha_state()
None update_target_temperature(self, float target_temperature)
Definition: climate.py:151
None update_temperature(self, float current_temperature)
Definition: climate.py:157
None set_hvac_mode(self, HVACMode hvac_mode)
Definition: climate.py:147
None __init__(self, ConfigEntry config_entry, LivisiDataUpdateCoordinator coordinator, dict[str, Any] device)
Definition: climate.py:78
Any|None async_get_device_state(self, str capability, str key)
Definition: coordinator.py:94
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: climate.py:37
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103