Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for EnergyZero sensors."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from datetime import datetime, timedelta
8 
10  DOMAIN as SENSOR_DOMAIN,
11  SensorDeviceClass,
12  SensorEntity,
13  SensorEntityDescription,
14  SensorStateClass,
15 )
16 from homeassistant.config_entries import ConfigEntry
17 from homeassistant.const import (
18  CURRENCY_EURO,
19  PERCENTAGE,
20  UnitOfEnergy,
21  UnitOfTime,
22  UnitOfVolume,
23 )
24 from homeassistant.core import HomeAssistant
25 from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
26 from homeassistant.helpers.entity_platform import AddEntitiesCallback
27 from homeassistant.helpers.update_coordinator import CoordinatorEntity
28 
29 from .const import DOMAIN, SERVICE_TYPE_DEVICE_NAMES
30 from .coordinator import EnergyZeroData, EnergyZeroDataUpdateCoordinator
31 
32 
33 @dataclass(frozen=True, kw_only=True)
35  """Describes an EnergyZero sensor entity."""
36 
37  value_fn: Callable[[EnergyZeroData], float | datetime | None]
38  service_type: str
39 
40 
41 SENSORS: tuple[EnergyZeroSensorEntityDescription, ...] = (
43  key="current_hour_price",
44  translation_key="current_hour_price",
45  service_type="today_gas",
46  state_class=SensorStateClass.MEASUREMENT,
47  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfVolume.CUBIC_METERS}",
48  value_fn=lambda data: data.gas_today.current_price if data.gas_today else None,
49  ),
51  key="next_hour_price",
52  translation_key="next_hour_price",
53  service_type="today_gas",
54  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfVolume.CUBIC_METERS}",
55  value_fn=lambda data: get_gas_price(data, 1),
56  ),
58  key="current_hour_price",
59  translation_key="current_hour_price",
60  service_type="today_energy",
61  state_class=SensorStateClass.MEASUREMENT,
62  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
63  value_fn=lambda data: data.energy_today.current_price,
64  ),
66  key="next_hour_price",
67  translation_key="next_hour_price",
68  service_type="today_energy",
69  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
70  value_fn=lambda data: data.energy_today.price_at_time(
71  data.energy_today.utcnow() + timedelta(hours=1)
72  ),
73  ),
75  key="average_price",
76  translation_key="average_price",
77  service_type="today_energy",
78  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
79  value_fn=lambda data: data.energy_today.average_price,
80  ),
82  key="max_price",
83  translation_key="max_price",
84  service_type="today_energy",
85  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
86  value_fn=lambda data: data.energy_today.extreme_prices[1],
87  ),
89  key="min_price",
90  translation_key="min_price",
91  service_type="today_energy",
92  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
93  value_fn=lambda data: data.energy_today.extreme_prices[0],
94  ),
96  key="highest_price_time",
97  translation_key="highest_price_time",
98  service_type="today_energy",
99  device_class=SensorDeviceClass.TIMESTAMP,
100  value_fn=lambda data: data.energy_today.highest_price_time,
101  ),
103  key="lowest_price_time",
104  translation_key="lowest_price_time",
105  service_type="today_energy",
106  device_class=SensorDeviceClass.TIMESTAMP,
107  value_fn=lambda data: data.energy_today.lowest_price_time,
108  ),
110  key="percentage_of_max",
111  translation_key="percentage_of_max",
112  service_type="today_energy",
113  native_unit_of_measurement=PERCENTAGE,
114  value_fn=lambda data: data.energy_today.pct_of_max_price,
115  ),
117  key="hours_priced_equal_or_lower",
118  translation_key="hours_priced_equal_or_lower",
119  service_type="today_energy",
120  native_unit_of_measurement=UnitOfTime.HOURS,
121  value_fn=lambda data: data.energy_today.hours_priced_equal_or_lower,
122  ),
123 )
124 
125 
126 def get_gas_price(data: EnergyZeroData, hours: int) -> float | None:
127  """Return the gas value.
128 
129  Args:
130  data: The data object.
131  hours: The number of hours to add to the current time.
132 
133  Returns:
134  The gas market price value.
135 
136  """
137  if data.gas_today is None:
138  return None
139  return data.gas_today.price_at_time(
140  data.gas_today.utcnow() + timedelta(hours=hours)
141  )
142 
143 
145  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
146 ) -> None:
147  """Set up EnergyZero Sensors based on a config entry."""
148  coordinator: EnergyZeroDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
151  coordinator=coordinator,
152  description=description,
153  )
154  for description in SENSORS
155  )
156 
157 
159  CoordinatorEntity[EnergyZeroDataUpdateCoordinator], SensorEntity
160 ):
161  """Defines a EnergyZero sensor."""
162 
163  _attr_has_entity_name = True
164  _attr_attribution = "Data provided by EnergyZero"
165  entity_description: EnergyZeroSensorEntityDescription
166 
167  def __init__(
168  self,
169  *,
170  coordinator: EnergyZeroDataUpdateCoordinator,
171  description: EnergyZeroSensorEntityDescription,
172  ) -> None:
173  """Initialize EnergyZero sensor."""
174  super().__init__(coordinator=coordinator)
175  self.entity_descriptionentity_description = description
176  self.entity_identity_identity_id = (
177  f"{SENSOR_DOMAIN}.{DOMAIN}_{description.service_type}_{description.key}"
178  )
179  self._attr_unique_id_attr_unique_id = f"{coordinator.config_entry.entry_id}_{description.service_type}_{description.key}"
180  self._attr_device_info_attr_device_info = DeviceInfo(
181  entry_type=DeviceEntryType.SERVICE,
182  identifiers={
183  (
184  DOMAIN,
185  f"{coordinator.config_entry.entry_id}_{description.service_type}",
186  )
187  },
188  manufacturer="EnergyZero",
189  name=SERVICE_TYPE_DEVICE_NAMES[self.entity_descriptionentity_description.service_type],
190  )
191 
192  @property
193  def native_value(self) -> float | datetime | None:
194  """Return the state of the sensor."""
195  return self.entity_descriptionentity_description.value_fn(self.coordinator.data)
None __init__(self, *EnergyZeroDataUpdateCoordinator coordinator, EnergyZeroSensorEntityDescription description)
Definition: sensor.py:172
float|None get_gas_price(EnergyZeroData data, int hours)
Definition: sensor.py:126
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:146