Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Platform for sensor integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from datetime import datetime
8 import logging
9 
10 from ultraheat_api.response import HeatMeterResponse
11 
13  SensorDeviceClass,
14  SensorEntity,
15  SensorEntityDescription,
16  SensorStateClass,
17 )
18 from homeassistant.config_entries import ConfigEntry
19 from homeassistant.const import (
20  EntityCategory,
21  UnitOfEnergy,
22  UnitOfPower,
23  UnitOfTemperature,
24  UnitOfTime,
25  UnitOfVolume,
26  UnitOfVolumeFlowRate,
27 )
28 from homeassistant.core import HomeAssistant
29 from homeassistant.helpers.device_registry import DeviceInfo
30 from homeassistant.helpers.entity_platform import AddEntitiesCallback
31 from homeassistant.helpers.typing import StateType
33  CoordinatorEntity,
34  DataUpdateCoordinator,
35 )
36 from homeassistant.util import dt as dt_util
37 
38 from . import DOMAIN
39 
40 _LOGGER = logging.getLogger(__name__)
41 
42 
43 @dataclass(frozen=True, kw_only=True)
45  """Heat Meter sensor description."""
46 
47  value_fn: Callable[[HeatMeterResponse], StateType | datetime]
48 
49 
50 HEAT_METER_SENSOR_TYPES = (
52  key="heat_usage_mwh",
53  icon="mdi:fire",
54  name="Heat usage MWh",
55  native_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
56  device_class=SensorDeviceClass.ENERGY,
57  state_class=SensorStateClass.TOTAL,
58  value_fn=lambda res: res.heat_usage_mwh,
59  ),
61  key="volume_usage_m3",
62  icon="mdi:fire",
63  name="Volume usage",
64  device_class=SensorDeviceClass.VOLUME,
65  native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
66  state_class=SensorStateClass.TOTAL,
67  value_fn=lambda res: res.volume_usage_m3,
68  ),
70  key="heat_usage_gj",
71  icon="mdi:fire",
72  name="Heat usage GJ",
73  native_unit_of_measurement=UnitOfEnergy.GIGA_JOULE,
74  device_class=SensorDeviceClass.ENERGY,
75  state_class=SensorStateClass.TOTAL,
76  value_fn=lambda res: res.heat_usage_gj,
77  ),
79  key="heat_previous_year_mwh",
80  icon="mdi:fire",
81  name="Heat previous year MWh",
82  native_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
83  device_class=SensorDeviceClass.ENERGY,
84  entity_category=EntityCategory.DIAGNOSTIC,
85  value_fn=lambda res: res.heat_previous_year_mwh,
86  ),
88  key="heat_previous_year_gj",
89  icon="mdi:fire",
90  name="Heat previous year GJ",
91  native_unit_of_measurement=UnitOfEnergy.GIGA_JOULE,
92  device_class=SensorDeviceClass.ENERGY,
93  entity_category=EntityCategory.DIAGNOSTIC,
94  value_fn=lambda res: res.heat_previous_year_gj,
95  ),
97  key="volume_previous_year_m3",
98  icon="mdi:fire",
99  name="Volume usage previous year",
100  device_class=SensorDeviceClass.VOLUME,
101  native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
102  entity_category=EntityCategory.DIAGNOSTIC,
103  value_fn=lambda res: res.volume_previous_year_m3,
104  ),
106  key="ownership_number",
107  name="Ownership number",
108  icon="mdi:identifier",
109  entity_category=EntityCategory.DIAGNOSTIC,
110  value_fn=lambda res: res.ownership_number,
111  ),
113  key="error_number",
114  name="Error number",
115  icon="mdi:home-alert",
116  entity_category=EntityCategory.DIAGNOSTIC,
117  value_fn=lambda res: res.error_number,
118  ),
120  key="device_number",
121  name="Device number",
122  icon="mdi:identifier",
123  entity_category=EntityCategory.DIAGNOSTIC,
124  value_fn=lambda res: res.device_number,
125  ),
127  key="measurement_period_minutes",
128  name="Measurement period minutes",
129  device_class=SensorDeviceClass.DURATION,
130  native_unit_of_measurement=UnitOfTime.MINUTES,
131  entity_category=EntityCategory.DIAGNOSTIC,
132  value_fn=lambda res: res.measurement_period_minutes,
133  ),
135  key="power_max_kw",
136  name="Power max",
137  native_unit_of_measurement=UnitOfPower.KILO_WATT,
138  device_class=SensorDeviceClass.POWER,
139  entity_category=EntityCategory.DIAGNOSTIC,
140  value_fn=lambda res: res.power_max_kw,
141  ),
143  key="power_max_previous_year_kw",
144  name="Power max previous year",
145  native_unit_of_measurement=UnitOfPower.KILO_WATT,
146  device_class=SensorDeviceClass.POWER,
147  entity_category=EntityCategory.DIAGNOSTIC,
148  value_fn=lambda res: res.power_max_previous_year_kw,
149  ),
151  key="flowrate_max_m3ph",
152  name="Flowrate max",
153  native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
154  icon="mdi:water-outline",
155  entity_category=EntityCategory.DIAGNOSTIC,
156  value_fn=lambda res: res.flowrate_max_m3ph,
157  ),
159  key="flowrate_max_previous_year_m3ph",
160  name="Flowrate max previous year",
161  native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
162  icon="mdi:water-outline",
163  entity_category=EntityCategory.DIAGNOSTIC,
164  value_fn=lambda res: res.flowrate_max_previous_year_m3ph,
165  ),
167  key="return_temperature_max_c",
168  name="Return temperature max",
169  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
170  device_class=SensorDeviceClass.TEMPERATURE,
171  entity_category=EntityCategory.DIAGNOSTIC,
172  value_fn=lambda res: res.return_temperature_max_c,
173  ),
175  key="return_temperature_max_previous_year_c",
176  name="Return temperature max previous year",
177  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
178  device_class=SensorDeviceClass.TEMPERATURE,
179  entity_category=EntityCategory.DIAGNOSTIC,
180  value_fn=lambda res: res.return_temperature_max_previous_year_c,
181  ),
183  key="flow_temperature_max_c",
184  name="Flow temperature max",
185  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
186  device_class=SensorDeviceClass.TEMPERATURE,
187  entity_category=EntityCategory.DIAGNOSTIC,
188  value_fn=lambda res: res.flow_temperature_max_c,
189  ),
191  key="flow_temperature_max_previous_year_c",
192  name="Flow temperature max previous year",
193  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
194  device_class=SensorDeviceClass.TEMPERATURE,
195  entity_category=EntityCategory.DIAGNOSTIC,
196  value_fn=lambda res: res.flow_temperature_max_previous_year_c,
197  ),
199  key="operating_hours",
200  name="Operating hours",
201  device_class=SensorDeviceClass.DURATION,
202  native_unit_of_measurement=UnitOfTime.HOURS,
203  entity_category=EntityCategory.DIAGNOSTIC,
204  value_fn=lambda res: res.operating_hours,
205  ),
207  key="flow_hours",
208  name="Flow hours",
209  device_class=SensorDeviceClass.DURATION,
210  native_unit_of_measurement=UnitOfTime.HOURS,
211  entity_category=EntityCategory.DIAGNOSTIC,
212  value_fn=lambda res: res.flow_hours,
213  ),
215  key="fault_hours",
216  name="Fault hours",
217  device_class=SensorDeviceClass.DURATION,
218  native_unit_of_measurement=UnitOfTime.HOURS,
219  entity_category=EntityCategory.DIAGNOSTIC,
220  value_fn=lambda res: res.fault_hours,
221  ),
223  key="fault_hours_previous_year",
224  name="Fault hours previous year",
225  device_class=SensorDeviceClass.DURATION,
226  native_unit_of_measurement=UnitOfTime.HOURS,
227  entity_category=EntityCategory.DIAGNOSTIC,
228  value_fn=lambda res: res.fault_hours_previous_year,
229  ),
231  key="yearly_set_day",
232  name="Yearly set day",
233  icon="mdi:clock-outline",
234  entity_category=EntityCategory.DIAGNOSTIC,
235  value_fn=lambda res: res.yearly_set_day,
236  ),
238  key="monthly_set_day",
239  name="Monthly set day",
240  icon="mdi:clock-outline",
241  entity_category=EntityCategory.DIAGNOSTIC,
242  value_fn=lambda res: res.monthly_set_day,
243  ),
245  key="meter_date_time",
246  name="Meter date time",
247  icon="mdi:clock-outline",
248  device_class=SensorDeviceClass.TIMESTAMP,
249  entity_category=EntityCategory.DIAGNOSTIC,
250  value_fn=lambda res: dt_util.as_utc(res.meter_date_time)
251  if res.meter_date_time
252  else None,
253  ),
255  key="measuring_range_m3ph",
256  name="Measuring range",
257  native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
258  icon="mdi:water-outline",
259  entity_category=EntityCategory.DIAGNOSTIC,
260  value_fn=lambda res: res.measuring_range_m3ph,
261  ),
263  key="settings_and_firmware",
264  name="Settings and firmware",
265  entity_category=EntityCategory.DIAGNOSTIC,
266  value_fn=lambda res: res.settings_and_firmware,
267  ),
268 )
269 
270 
272  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
273 ) -> None:
274  """Set up the sensor platform."""
275  unique_id = entry.entry_id
276  coordinator: DataUpdateCoordinator[HeatMeterResponse] = hass.data[DOMAIN][
277  entry.entry_id
278  ]
279 
280  model = entry.data["model"]
281 
282  device = DeviceInfo(
283  identifiers={(DOMAIN, unique_id)},
284  manufacturer="Landis & Gyr",
285  model=model,
286  name="Landis+Gyr Heat Meter",
287  )
288 
290  HeatMeterSensor(coordinator, description, device)
291  for description in HEAT_METER_SENSOR_TYPES
292  )
293 
294 
296  CoordinatorEntity[DataUpdateCoordinator[HeatMeterResponse]],
297  SensorEntity,
298 ):
299  """Representation of a Sensor."""
300 
301  entity_description: HeatMeterSensorEntityDescription
302 
303  def __init__(
304  self,
305  coordinator: DataUpdateCoordinator[HeatMeterResponse],
306  description: HeatMeterSensorEntityDescription,
307  device: DeviceInfo,
308  ) -> None:
309  """Set up the sensor with the initial values."""
310  super().__init__(coordinator)
311  self.keykey = description.key
312  self._attr_unique_id_attr_unique_id = (
313  f"{coordinator.config_entry.data['device_number']}_{description.key}" # type: ignore[union-attr]
314  )
315  self._attr_name_attr_name = f"Heat Meter {description.name}"
316  self.entity_descriptionentity_description = description
317  self._attr_device_info_attr_device_info = device
318 
319  if (
320  description.native_unit_of_measurement
321  in {UnitOfEnergy.GIGA_JOULE, UnitOfEnergy.MEGA_WATT_HOUR}
322  and self.native_valuenative_valuenative_value is None
323  ):
324  # Some meters will return MWh, others will return GJ.
325  self._attr_entity_registry_enabled_default_attr_entity_registry_enabled_default = False
326 
327  @property
328  def native_value(self) -> StateType | datetime:
329  """Return the state of the sensor."""
330  return self.entity_descriptionentity_description.value_fn(self.coordinator.data)
None __init__(self, DataUpdateCoordinator[HeatMeterResponse] coordinator, HeatMeterSensorEntityDescription description, DeviceInfo device)
Definition: sensor.py:308
StateType|date|datetime|Decimal native_value(self)
Definition: __init__.py:460
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:273