Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Vallox ventilation unit sensors."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass
6 from datetime import datetime, time
7 
9  SensorDeviceClass,
10  SensorEntity,
11  SensorEntityDescription,
12  SensorStateClass,
13 )
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.const import (
16  CONCENTRATION_PARTS_PER_MILLION,
17  PERCENTAGE,
18  REVOLUTIONS_PER_MINUTE,
19  EntityCategory,
20  UnitOfTemperature,
21  UnitOfTime,
22 )
23 from homeassistant.core import HomeAssistant
24 from homeassistant.helpers.entity_platform import AddEntitiesCallback
25 from homeassistant.helpers.typing import StateType
26 from homeassistant.util import dt as dt_util
27 
28 from .const import (
29  DOMAIN,
30  METRIC_KEY_MODE,
31  MODE_ON,
32  VALLOX_CELL_STATE_TO_STR,
33  VALLOX_PROFILE_TO_PRESET_MODE,
34 )
35 from .coordinator import ValloxDataUpdateCoordinator
36 from .entity import ValloxEntity
37 
38 
40  """Representation of a Vallox sensor."""
41 
42  entity_description: ValloxSensorEntityDescription
43  _attr_entity_category = EntityCategory.DIAGNOSTIC
44 
45  def __init__(
46  self,
47  name: str,
48  coordinator: ValloxDataUpdateCoordinator,
49  description: ValloxSensorEntityDescription,
50  ) -> None:
51  """Initialize the Vallox sensor."""
52  super().__init__(name, coordinator)
53 
54  self.entity_descriptionentity_description = description
55 
56  self._attr_unique_id_attr_unique_id = f"{self._device_uuid}-{description.key}"
57 
58  @property
59  def native_value(self) -> StateType | datetime:
60  """Return the value reported by the sensor."""
61  if (metric_key := self.entity_descriptionentity_description.metric_key) is None:
62  return None
63 
64  value = self.coordinator.data.get(metric_key)
65 
66  if self.entity_descriptionentity_description.round_ndigits is not None and isinstance(
67  value, float
68  ):
69  value = round(value, self.entity_descriptionentity_description.round_ndigits)
70 
71  return value
72 
73 
75  """Child class for profile reporting."""
76 
77  @property
78  def native_value(self) -> StateType:
79  """Return the value reported by the sensor."""
80  vallox_profile = self.coordinator.data.profile
81  return VALLOX_PROFILE_TO_PRESET_MODE.get(vallox_profile)
82 
83 
84 # There is a quirk with respect to the fan speed reporting. The device keeps on reporting the last
85 # valid fan speed from when the device was in regular operation mode, even if it left that state and
86 # has been shut off in the meantime.
87 #
88 # Therefore, first query the overall state of the device, and report zero percent fan speed in case
89 # it is not in regular operation mode.
91  """Child class for fan speed reporting."""
92 
93  @property
94  def native_value(self) -> StateType | datetime:
95  """Return the value reported by the sensor."""
96  fan_is_on = self.coordinator.data.get(METRIC_KEY_MODE) == MODE_ON
97  return super().native_value if fan_is_on else 0
98 
99 
101  """Child class for filter remaining time reporting."""
102 
103  @property
104  def native_value(self) -> StateType | datetime:
105  """Return the value reported by the sensor."""
106  next_filter_change_date = self.coordinator.data.next_filter_change_date
107 
108  if next_filter_change_date is None:
109  return None
110 
111  return datetime.combine(
112  next_filter_change_date,
113  time(hour=13, minute=0, second=0, tzinfo=dt_util.get_default_time_zone()),
114  )
115 
116 
118  """Child class for cell state reporting."""
119 
120  @property
121  def native_value(self) -> StateType:
122  """Return the value reported by the sensor."""
123  super_native_value = super().native_value
124 
125  if not isinstance(super_native_value, int):
126  return None
127 
128  return VALLOX_CELL_STATE_TO_STR.get(super_native_value)
129 
130 
132  """Child class for profile duration reporting."""
133 
134  @property
135  def native_value(self) -> StateType:
136  """Return the value reported by the sensor."""
137 
138  return self.coordinator.data.get_remaining_profile_duration(
139  self.coordinator.data.profile
140  )
141 
142 
143 @dataclass(frozen=True)
145  """Describes Vallox sensor entity."""
146 
147  metric_key: str | None = None
148  entity_type: type[ValloxSensorEntity] = ValloxSensorEntity
149  round_ndigits: int | None = None
150 
151 
152 SENSOR_ENTITIES: tuple[ValloxSensorEntityDescription, ...] = (
154  key="current_profile",
155  translation_key="current_profile",
156  entity_type=ValloxProfileSensor,
157  ),
159  key="fan_speed",
160  translation_key="fan_speed",
161  metric_key="A_CYC_FAN_SPEED",
162  state_class=SensorStateClass.MEASUREMENT,
163  native_unit_of_measurement=PERCENTAGE,
164  entity_type=ValloxFanSpeedSensor,
165  ),
167  key="extract_fan_speed",
168  translation_key="extract_fan_speed",
169  metric_key="A_CYC_EXTR_FAN_SPEED",
170  state_class=SensorStateClass.MEASUREMENT,
171  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
172  entity_type=ValloxFanSpeedSensor,
173  entity_registry_enabled_default=False,
174  ),
176  key="supply_fan_speed",
177  translation_key="supply_fan_speed",
178  metric_key="A_CYC_SUPP_FAN_SPEED",
179  state_class=SensorStateClass.MEASUREMENT,
180  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
181  entity_type=ValloxFanSpeedSensor,
182  entity_registry_enabled_default=False,
183  ),
185  key="remaining_time_for_filter",
186  translation_key="remaining_time_for_filter",
187  device_class=SensorDeviceClass.TIMESTAMP,
188  entity_type=ValloxFilterRemainingSensor,
189  ),
191  key="cell_state",
192  translation_key="cell_state",
193  metric_key="A_CYC_CELL_STATE",
194  entity_type=ValloxCellStateSensor,
195  ),
197  key="extract_air",
198  translation_key="extract_air",
199  metric_key="A_CYC_TEMP_EXTRACT_AIR",
200  device_class=SensorDeviceClass.TEMPERATURE,
201  state_class=SensorStateClass.MEASUREMENT,
202  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
203  ),
205  key="exhaust_air",
206  translation_key="exhaust_air",
207  metric_key="A_CYC_TEMP_EXHAUST_AIR",
208  device_class=SensorDeviceClass.TEMPERATURE,
209  state_class=SensorStateClass.MEASUREMENT,
210  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
211  ),
213  key="outdoor_air",
214  translation_key="outdoor_air",
215  metric_key="A_CYC_TEMP_OUTDOOR_AIR",
216  device_class=SensorDeviceClass.TEMPERATURE,
217  state_class=SensorStateClass.MEASUREMENT,
218  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
219  ),
221  key="supply_air",
222  translation_key="supply_air",
223  metric_key="A_CYC_TEMP_SUPPLY_AIR",
224  device_class=SensorDeviceClass.TEMPERATURE,
225  state_class=SensorStateClass.MEASUREMENT,
226  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
227  ),
229  key="supply_cell_air",
230  translation_key="supply_cell_air",
231  metric_key="A_CYC_TEMP_SUPPLY_CELL_AIR",
232  device_class=SensorDeviceClass.TEMPERATURE,
233  state_class=SensorStateClass.MEASUREMENT,
234  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
235  ),
237  key="optional_air",
238  translation_key="optional_air",
239  metric_key="A_CYC_TEMP_OPTIONAL",
240  device_class=SensorDeviceClass.TEMPERATURE,
241  state_class=SensorStateClass.MEASUREMENT,
242  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
243  entity_registry_enabled_default=False,
244  ),
246  key="humidity",
247  metric_key="A_CYC_RH_VALUE",
248  device_class=SensorDeviceClass.HUMIDITY,
249  state_class=SensorStateClass.MEASUREMENT,
250  native_unit_of_measurement=PERCENTAGE,
251  ),
253  key="efficiency",
254  translation_key="efficiency",
255  metric_key="A_CYC_EXTRACT_EFFICIENCY",
256  state_class=SensorStateClass.MEASUREMENT,
257  native_unit_of_measurement=PERCENTAGE,
258  entity_registry_enabled_default=False,
259  round_ndigits=0,
260  ),
262  key="co2",
263  metric_key="A_CYC_CO2_VALUE",
264  device_class=SensorDeviceClass.CO2,
265  state_class=SensorStateClass.MEASUREMENT,
266  native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
267  entity_registry_enabled_default=False,
268  ),
270  key="profile_duration",
271  translation_key="profile_duration",
272  device_class=SensorDeviceClass.DURATION,
273  state_class=SensorStateClass.MEASUREMENT,
274  native_unit_of_measurement=UnitOfTime.MINUTES,
275  entity_type=ValloxProfileDurationSensor,
276  ),
277 )
278 
279 
281  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
282 ) -> None:
283  """Set up the sensors."""
284  name = hass.data[DOMAIN][entry.entry_id]["name"]
285  coordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
286 
288  description.entity_type(name, coordinator, description)
289  for description in SENSOR_ENTITIES
290  )
None __init__(self, str name, ValloxDataUpdateCoordinator coordinator, ValloxSensorEntityDescription description)
Definition: sensor.py:50
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:282
bool time(HomeAssistant hass, dt_time|str|None before=None, dt_time|str|None after=None, str|Container[str]|None weekday=None)
Definition: condition.py:802