Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for easyEnergy 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 EasyEnergyData, EasyEnergyDataUpdateCoordinator
31 
32 
33 @dataclass(frozen=True, kw_only=True)
35  """Describes easyEnergy sensor entity."""
36 
37  value_fn: Callable[[EasyEnergyData], float | datetime | None]
38  service_type: str
39 
40 
41 SENSORS: tuple[EasyEnergySensorEntityDescription, ...] = (
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_usage",
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_usage_price,
64  ),
66  key="next_hour_price",
67  translation_key="next_hour_price",
68  service_type="today_energy_usage",
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_usage",
78  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
79  value_fn=lambda data: data.energy_today.average_usage_price,
80  ),
82  key="max_price",
83  translation_key="max_price",
84  service_type="today_energy_usage",
85  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
86  value_fn=lambda data: data.energy_today.extreme_usage_prices[1],
87  ),
89  key="min_price",
90  translation_key="min_price",
91  service_type="today_energy_usage",
92  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
93  value_fn=lambda data: data.energy_today.extreme_usage_prices[0],
94  ),
96  key="highest_price_time",
97  translation_key="highest_price_time",
98  service_type="today_energy_usage",
99  device_class=SensorDeviceClass.TIMESTAMP,
100  value_fn=lambda data: data.energy_today.highest_usage_price_time,
101  ),
103  key="lowest_price_time",
104  translation_key="lowest_price_time",
105  service_type="today_energy_usage",
106  device_class=SensorDeviceClass.TIMESTAMP,
107  value_fn=lambda data: data.energy_today.lowest_usage_price_time,
108  ),
110  key="percentage_of_max",
111  translation_key="percentage_of_max",
112  service_type="today_energy_usage",
113  native_unit_of_measurement=PERCENTAGE,
114  value_fn=lambda data: data.energy_today.pct_of_max_usage,
115  ),
117  key="current_hour_price",
118  translation_key="current_hour_price",
119  service_type="today_energy_return",
120  state_class=SensorStateClass.MEASUREMENT,
121  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
122  value_fn=lambda data: data.energy_today.current_return_price,
123  ),
125  key="next_hour_price",
126  translation_key="next_hour_price",
127  service_type="today_energy_return",
128  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
129  value_fn=lambda data: data.energy_today.price_at_time(
130  data.energy_today.utcnow() + timedelta(hours=1), "return"
131  ),
132  ),
134  key="average_price",
135  translation_key="average_price",
136  service_type="today_energy_return",
137  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
138  value_fn=lambda data: data.energy_today.average_return_price,
139  ),
141  key="max_price",
142  translation_key="max_price",
143  service_type="today_energy_return",
144  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
145  value_fn=lambda data: data.energy_today.extreme_return_prices[1],
146  ),
148  key="min_price",
149  translation_key="min_price",
150  service_type="today_energy_return",
151  native_unit_of_measurement=f"{CURRENCY_EURO}/{UnitOfEnergy.KILO_WATT_HOUR}",
152  value_fn=lambda data: data.energy_today.extreme_return_prices[0],
153  ),
155  key="highest_price_time",
156  translation_key="highest_price_time",
157  service_type="today_energy_return",
158  device_class=SensorDeviceClass.TIMESTAMP,
159  value_fn=lambda data: data.energy_today.highest_return_price_time,
160  ),
162  key="lowest_price_time",
163  translation_key="lowest_price_time",
164  service_type="today_energy_return",
165  device_class=SensorDeviceClass.TIMESTAMP,
166  value_fn=lambda data: data.energy_today.lowest_return_price_time,
167  ),
169  key="percentage_of_max",
170  translation_key="percentage_of_max",
171  service_type="today_energy_return",
172  native_unit_of_measurement=PERCENTAGE,
173  value_fn=lambda data: data.energy_today.pct_of_max_return,
174  ),
176  key="hours_priced_equal_or_lower",
177  translation_key="hours_priced_equal_or_lower",
178  service_type="today_energy_usage",
179  native_unit_of_measurement=UnitOfTime.HOURS,
180  value_fn=lambda data: data.energy_today.hours_priced_equal_or_lower_usage,
181  ),
183  key="hours_priced_equal_or_higher",
184  translation_key="hours_priced_equal_or_higher",
185  service_type="today_energy_return",
186  native_unit_of_measurement=UnitOfTime.HOURS,
187  value_fn=lambda data: data.energy_today.hours_priced_equal_or_higher_return,
188  ),
189 )
190 
191 
192 def get_gas_price(data: EasyEnergyData, hours: int) -> float | None:
193  """Return the gas value.
194 
195  Args:
196  data: The data object.
197  hours: The number of hours to add to the current time.
198 
199  Returns:
200  The gas market price value.
201 
202  """
203  if data.gas_today is None:
204  return None
205  return data.gas_today.price_at_time(
206  data.gas_today.utcnow() + timedelta(hours=hours)
207  )
208 
209 
211  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
212 ) -> None:
213  """Set up easyEnergy sensors based on a config entry."""
214  coordinator: EasyEnergyDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
216  EasyEnergySensorEntity(coordinator=coordinator, description=description)
217  for description in SENSORS
218  )
219 
220 
222  CoordinatorEntity[EasyEnergyDataUpdateCoordinator], SensorEntity
223 ):
224  """Defines an easyEnergy sensor."""
225 
226  _attr_has_entity_name = True
227  _attr_attribution = "Data provided by easyEnergy"
228  entity_description: EasyEnergySensorEntityDescription
229 
230  def __init__(
231  self,
232  *,
233  coordinator: EasyEnergyDataUpdateCoordinator,
234  description: EasyEnergySensorEntityDescription,
235  ) -> None:
236  """Initialize easyEnergy sensor."""
237  super().__init__(coordinator=coordinator)
238  self.entity_descriptionentity_description = description
239  self.entity_identity_identity_id = (
240  f"{SENSOR_DOMAIN}.{DOMAIN}_{description.service_type}_{description.key}"
241  )
242  self._attr_unique_id_attr_unique_id = f"{coordinator.config_entry.entry_id}_{description.service_type}_{description.key}"
243  self._attr_device_info_attr_device_info = DeviceInfo(
244  entry_type=DeviceEntryType.SERVICE,
245  identifiers={
246  (
247  DOMAIN,
248  f"{coordinator.config_entry.entry_id}_{description.service_type}",
249  )
250  },
251  configuration_url="https://www.easyenergy.com",
252  manufacturer="easyEnergy",
253  name=SERVICE_TYPE_DEVICE_NAMES[self.entity_descriptionentity_description.service_type],
254  )
255 
256  @property
257  def native_value(self) -> float | datetime | None:
258  """Return the state of the sensor."""
259  return self.entity_descriptionentity_description.value_fn(self.coordinator.data)
None __init__(self, *EasyEnergyDataUpdateCoordinator coordinator, EasyEnergySensorEntityDescription description)
Definition: sensor.py:235
float|None get_gas_price(EasyEnergyData data, int hours)
Definition: sensor.py:192
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:212