Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for OVO Energy sensors."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 import dataclasses
7 from datetime import datetime, timedelta
8 from typing import Final
9 
10 from ovoenergy import OVOEnergy
11 from ovoenergy.models import OVODailyUsage
12 
14  SensorDeviceClass,
15  SensorEntity,
16  SensorEntityDescription,
17  SensorStateClass,
18 )
19 from homeassistant.config_entries import ConfigEntry
20 from homeassistant.const import UnitOfEnergy
21 from homeassistant.core import HomeAssistant
22 from homeassistant.helpers.entity_platform import AddEntitiesCallback
23 from homeassistant.helpers.typing import StateType
24 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
25 from homeassistant.util import dt as dt_util
26 
27 from .const import DATA_CLIENT, DATA_COORDINATOR, DOMAIN
28 from .entity import OVOEnergyDeviceEntity
29 
30 SCAN_INTERVAL = timedelta(seconds=300)
31 PARALLEL_UPDATES = 4
32 
33 KEY_LAST_ELECTRICITY_COST: Final = "last_electricity_cost"
34 KEY_LAST_GAS_COST: Final = "last_gas_cost"
35 
36 
37 @dataclasses.dataclass(frozen=True)
39  """Class describing System Bridge sensor entities."""
40 
41  value: Callable[[OVODailyUsage], StateType | datetime] = round
42 
43 
44 SENSOR_TYPES_ELECTRICITY: tuple[OVOEnergySensorEntityDescription, ...] = (
46  key="last_electricity_reading",
47  translation_key="last_electricity_reading",
48  device_class=SensorDeviceClass.ENERGY,
49  state_class=SensorStateClass.TOTAL_INCREASING,
50  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
51  value=lambda usage: usage.electricity[-1].consumption,
52  ),
54  key=KEY_LAST_ELECTRICITY_COST,
55  translation_key=KEY_LAST_ELECTRICITY_COST,
56  device_class=SensorDeviceClass.MONETARY,
57  state_class=SensorStateClass.TOTAL,
58  value=lambda usage: usage.electricity[-1].cost.amount
59  if usage.electricity[-1].cost is not None
60  else None,
61  ),
63  key="last_electricity_start_time",
64  translation_key="last_electricity_start_time",
65  entity_registry_enabled_default=False,
66  device_class=SensorDeviceClass.TIMESTAMP,
67  value=lambda usage: dt_util.as_utc(usage.electricity[-1].interval.start),
68  ),
70  key="last_electricity_end_time",
71  translation_key="last_electricity_end_time",
72  entity_registry_enabled_default=False,
73  device_class=SensorDeviceClass.TIMESTAMP,
74  value=lambda usage: dt_util.as_utc(usage.electricity[-1].interval.end),
75  ),
76 )
77 
78 SENSOR_TYPES_GAS: tuple[OVOEnergySensorEntityDescription, ...] = (
80  key="last_gas_reading",
81  translation_key="last_gas_reading",
82  device_class=SensorDeviceClass.ENERGY,
83  state_class=SensorStateClass.TOTAL_INCREASING,
84  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
85  value=lambda usage: usage.gas[-1].consumption,
86  ),
88  key=KEY_LAST_GAS_COST,
89  translation_key=KEY_LAST_GAS_COST,
90  device_class=SensorDeviceClass.MONETARY,
91  state_class=SensorStateClass.TOTAL,
92  value=lambda usage: usage.gas[-1].cost.amount
93  if usage.gas[-1].cost is not None
94  else None,
95  ),
97  key="last_gas_start_time",
98  translation_key="last_gas_start_time",
99  entity_registry_enabled_default=False,
100  device_class=SensorDeviceClass.TIMESTAMP,
101  value=lambda usage: dt_util.as_utc(usage.gas[-1].interval.start),
102  ),
104  key="last_gas_end_time",
105  translation_key="last_gas_end_time",
106  entity_registry_enabled_default=False,
107  device_class=SensorDeviceClass.TIMESTAMP,
108  value=lambda usage: dt_util.as_utc(usage.gas[-1].interval.end),
109  ),
110 )
111 
112 
114  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
115 ) -> None:
116  """Set up OVO Energy sensor based on a config entry."""
117  coordinator: DataUpdateCoordinator[OVODailyUsage] = hass.data[DOMAIN][
118  entry.entry_id
119  ][DATA_COORDINATOR]
120  client: OVOEnergy = hass.data[DOMAIN][entry.entry_id][DATA_CLIENT]
121 
122  entities = []
123 
124  if coordinator.data:
125  if coordinator.data.electricity:
126  for description in SENSOR_TYPES_ELECTRICITY:
127  if (
128  description.key == KEY_LAST_ELECTRICITY_COST
129  and coordinator.data.electricity[-1] is not None
130  and coordinator.data.electricity[-1].cost is not None
131  ):
132  description = dataclasses.replace(
133  description,
134  native_unit_of_measurement=(
135  coordinator.data.electricity[-1].cost.currency_unit
136  ),
137  )
138  entities.append(OVOEnergySensor(coordinator, description, client))
139  if coordinator.data.gas:
140  for description in SENSOR_TYPES_GAS:
141  if (
142  description.key == KEY_LAST_GAS_COST
143  and coordinator.data.gas[-1] is not None
144  and coordinator.data.gas[-1].cost is not None
145  ):
146  description = dataclasses.replace(
147  description,
148  native_unit_of_measurement=coordinator.data.gas[
149  -1
150  ].cost.currency_unit,
151  )
152  entities.append(OVOEnergySensor(coordinator, description, client))
153 
154  async_add_entities(entities, True)
155 
156 
158  """Define a OVO Energy sensor."""
159 
160  coordinator: DataUpdateCoordinator[DataUpdateCoordinator[OVODailyUsage]]
161  entity_description: OVOEnergySensorEntityDescription
162 
163  def __init__(
164  self,
165  coordinator: DataUpdateCoordinator[OVODailyUsage],
166  description: OVOEnergySensorEntityDescription,
167  client: OVOEnergy,
168  ) -> None:
169  """Initialize."""
170  super().__init__(coordinator, client)
171  self._attr_unique_id_attr_unique_id = f"{DOMAIN}_{client.account_id}_{description.key}"
172  self.entity_descriptionentity_description = description
173 
174  @property
175  def native_value(self) -> StateType | datetime:
176  """Return the state."""
177  usage = self.coordinator.data
178  return self.entity_descriptionentity_description.value(usage)
None __init__(self, DataUpdateCoordinator[OVODailyUsage] coordinator, OVOEnergySensorEntityDescription description, OVOEnergy client)
Definition: sensor.py:168
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:115