Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """The sensor entity for the Youless integration."""
2 
3 from __future__ import annotations
4 
5 from youless_api import YoulessAPI
6 from youless_api.youless_sensor import YoulessSensor
7 
9  SensorDeviceClass,
10  SensorEntity,
11  SensorStateClass,
12 )
13 from homeassistant.config_entries import ConfigEntry
14 from homeassistant.const import (
15  CONF_DEVICE,
16  UnitOfElectricCurrent,
17  UnitOfElectricPotential,
18  UnitOfEnergy,
19  UnitOfPower,
20  UnitOfVolume,
21 )
22 from homeassistant.core import HomeAssistant
23 from homeassistant.helpers.device_registry import DeviceInfo
24 from homeassistant.helpers.entity_platform import AddEntitiesCallback
25 from homeassistant.helpers.typing import StateType
27  CoordinatorEntity,
28  DataUpdateCoordinator,
29 )
30 
31 from . import DOMAIN
32 
33 
35  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
36 ) -> None:
37  """Initialize the integration."""
38  coordinator: DataUpdateCoordinator[YoulessAPI] = hass.data[DOMAIN][entry.entry_id]
39  device = entry.data[CONF_DEVICE]
40  if (device := entry.data[CONF_DEVICE]) is None:
41  device = entry.entry_id
42 
44  [
45  WaterSensor(coordinator, device),
46  GasSensor(coordinator, device),
48  coordinator, device, "low", SensorStateClass.TOTAL_INCREASING
49  ),
51  coordinator, device, "high", SensorStateClass.TOTAL_INCREASING
52  ),
53  EnergyMeterSensor(coordinator, device, "total", SensorStateClass.TOTAL),
54  CurrentPowerSensor(coordinator, device),
55  DeliveryMeterSensor(coordinator, device, "low"),
56  DeliveryMeterSensor(coordinator, device, "high"),
57  ExtraMeterSensor(coordinator, device, "total"),
58  ExtraMeterPowerSensor(coordinator, device, "usage"),
59  PhasePowerSensor(coordinator, device, 1),
60  PhaseVoltageSensor(coordinator, device, 1),
61  PhaseCurrentSensor(coordinator, device, 1),
62  PhasePowerSensor(coordinator, device, 2),
63  PhaseVoltageSensor(coordinator, device, 2),
64  PhaseCurrentSensor(coordinator, device, 2),
65  PhasePowerSensor(coordinator, device, 3),
66  PhaseVoltageSensor(coordinator, device, 3),
67  PhaseCurrentSensor(coordinator, device, 3),
68  ]
69  )
70 
71 
73  CoordinatorEntity[DataUpdateCoordinator[YoulessAPI]], SensorEntity
74 ):
75  """The base sensor for Youless."""
76 
77  def __init__(
78  self,
79  coordinator: DataUpdateCoordinator[YoulessAPI],
80  device: str,
81  device_group: str,
82  friendly_name: str,
83  sensor_id: str,
84  ) -> None:
85  """Create the sensor."""
86  super().__init__(coordinator)
87  self._attr_unique_id_attr_unique_id = f"{DOMAIN}_{device}_{sensor_id}"
88  self._attr_device_info_attr_device_info = DeviceInfo(
89  identifiers={(DOMAIN, f"{device}_{device_group}")},
90  manufacturer="YouLess",
91  model=self.coordinator.data.model,
92  name=friendly_name,
93  )
94 
95  @property
96  def get_sensor(self) -> YoulessSensor | None:
97  """Property to get the underlying sensor object."""
98  return None
99 
100  @property
101  def native_value(self) -> StateType:
102  """Determine the state value, only if a sensor is initialized."""
103  if self.get_sensorget_sensor is None:
104  return None
105 
106  return self.get_sensorget_sensor.value
107 
108  @property
109  def available(self) -> bool:
110  """Return a flag to indicate the sensor not being available."""
111  return super().available and self.get_sensorget_sensor is not None
112 
113 
115  """The Youless Water sensor."""
116 
117  _attr_native_unit_of_measurement = UnitOfVolume.CUBIC_METERS
118  _attr_device_class = SensorDeviceClass.WATER
119  _attr_state_class = SensorStateClass.TOTAL_INCREASING
120 
121  def __init__(
122  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str
123  ) -> None:
124  """Instantiate a Water sensor."""
125  super().__init__(coordinator, device, "water", "Water meter", "water")
126  self._attr_name_attr_name = "Water usage"
127  self._attr_icon_attr_icon = "mdi:water"
128 
129  @property
130  def get_sensor(self) -> YoulessSensor | None:
131  """Get the sensor for providing the value."""
132  return self.coordinator.data.water_meter
133 
134 
136  """The Youless gas sensor."""
137 
138  _attr_native_unit_of_measurement = UnitOfVolume.CUBIC_METERS
139  _attr_device_class = SensorDeviceClass.GAS
140  _attr_state_class = SensorStateClass.TOTAL_INCREASING
141 
142  def __init__(
143  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str
144  ) -> None:
145  """Instantiate a gas sensor."""
146  super().__init__(coordinator, device, "gas", "Gas meter", "gas")
147  self._attr_name_attr_name = "Gas usage"
148  self._attr_icon_attr_icon = "mdi:fire"
149 
150  @property
151  def get_sensor(self) -> YoulessSensor | None:
152  """Get the sensor for providing the value."""
153  return self.coordinator.data.gas_meter
154 
155 
157  """The current power usage sensor."""
158 
159  _attr_native_unit_of_measurement = UnitOfPower.WATT
160  _attr_device_class = SensorDeviceClass.POWER
161  _attr_state_class = SensorStateClass.MEASUREMENT
162 
163  def __init__(
164  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str
165  ) -> None:
166  """Instantiate the usage meter."""
167  super().__init__(coordinator, device, "power", "Power usage", "usage")
168  self._device_device = device
169  self._attr_name_attr_name = "Power Usage"
170 
171  @property
172  def get_sensor(self) -> YoulessSensor | None:
173  """Get the sensor for providing the value."""
174  return self.coordinator.data.current_power_usage
175 
176 
178  """The Youless delivery meter value sensor."""
179 
180  _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
181  _attr_device_class = SensorDeviceClass.ENERGY
182  _attr_state_class = SensorStateClass.TOTAL_INCREASING
183 
184  def __init__(
185  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, dev_type: str
186  ) -> None:
187  """Instantiate a delivery meter sensor."""
188  super().__init__(
189  coordinator, device, "delivery", "Energy delivery", f"delivery_{dev_type}"
190  )
191  self._type_type = dev_type
192  self._attr_name_attr_name = f"Energy delivery {dev_type}"
193 
194  @property
195  def get_sensor(self) -> YoulessSensor | None:
196  """Get the sensor for providing the value."""
197  if self.coordinator.data.delivery_meter is None:
198  return None
199 
200  return getattr(self.coordinator.data.delivery_meter, f"_{self._type}", None)
201 
202 
204  """The Youless low meter value sensor."""
205 
206  _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
207  _attr_device_class = SensorDeviceClass.ENERGY
208  _attr_state_class = SensorStateClass.TOTAL_INCREASING
209 
210  def __init__(
211  self,
212  coordinator: DataUpdateCoordinator[YoulessAPI],
213  device: str,
214  dev_type: str,
215  state_class: SensorStateClass,
216  ) -> None:
217  """Instantiate a energy meter sensor."""
218  super().__init__(
219  coordinator, device, "power", "Energy usage", f"power_{dev_type}"
220  )
221  self._device_device = device
222  self._type_type = dev_type
223  self._attr_name_attr_name = f"Energy {dev_type}"
224  self._attr_state_class_attr_state_class = state_class
225 
226  @property
227  def get_sensor(self) -> YoulessSensor | None:
228  """Get the sensor for providing the value."""
229  if self.coordinator.data.power_meter is None:
230  return None
231 
232  return getattr(self.coordinator.data.power_meter, f"_{self._type}", None)
233 
234 
236  """The current power usage of a single phase."""
237 
238  _attr_native_unit_of_measurement = UnitOfPower.WATT
239  _attr_device_class = SensorDeviceClass.POWER
240  _attr_state_class = SensorStateClass.MEASUREMENT
241 
242  def __init__(
243  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, phase: int
244  ) -> None:
245  """Initialize the power phase sensor."""
246  super().__init__(
247  coordinator, device, "power", "Energy usage", f"phase_{phase}_power"
248  )
249  self._attr_name_attr_name = f"Phase {phase} power"
250  self._phase_phase = phase
251 
252  @property
253  def get_sensor(self) -> YoulessSensor | None:
254  """Get the sensor value from the coordinator."""
255  phase_sensor = getattr(self.coordinator.data, f"phase{self._phase}", None)
256  if phase_sensor is None:
257  return None
258 
259  return phase_sensor.power
260 
261 
263  """The current voltage of a single phase."""
264 
265  _attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT
266  _attr_device_class = SensorDeviceClass.VOLTAGE
267  _attr_state_class = SensorStateClass.MEASUREMENT
268 
269  def __init__(
270  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, phase: int
271  ) -> None:
272  """Initialize the voltage phase sensor."""
273  super().__init__(
274  coordinator, device, "power", "Energy usage", f"phase_{phase}_voltage"
275  )
276  self._attr_name_attr_name = f"Phase {phase} voltage"
277  self._phase_phase = phase
278 
279  @property
280  def get_sensor(self) -> YoulessSensor | None:
281  """Get the sensor value from the coordinator for phase voltage."""
282  phase_sensor = getattr(self.coordinator.data, f"phase{self._phase}", None)
283  if phase_sensor is None:
284  return None
285 
286  return phase_sensor.voltage
287 
288 
290  """The current current of a single phase."""
291 
292  _attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE
293  _attr_device_class = SensorDeviceClass.CURRENT
294  _attr_state_class = SensorStateClass.MEASUREMENT
295 
296  def __init__(
297  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, phase: int
298  ) -> None:
299  """Initialize the current phase sensor."""
300  super().__init__(
301  coordinator, device, "power", "Energy usage", f"phase_{phase}_current"
302  )
303  self._attr_name_attr_name = f"Phase {phase} current"
304  self._phase_phase = phase
305 
306  @property
307  def get_sensor(self) -> YoulessSensor | None:
308  """Get the sensor value from the coordinator for phase current."""
309  phase_sensor = getattr(self.coordinator.data, f"phase{self._phase}", None)
310  if phase_sensor is None:
311  return None
312 
313  return phase_sensor.current
314 
315 
317  """The Youless extra meter value sensor (s0)."""
318 
319  _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
320  _attr_device_class = SensorDeviceClass.ENERGY
321  _attr_state_class = SensorStateClass.TOTAL_INCREASING
322 
323  def __init__(
324  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, dev_type: str
325  ) -> None:
326  """Instantiate an extra meter sensor."""
327  super().__init__(
328  coordinator, device, "extra", "Extra meter", f"extra_{dev_type}"
329  )
330  self._type_type = dev_type
331  self._attr_name_attr_name = f"Extra {dev_type}"
332 
333  @property
334  def get_sensor(self) -> YoulessSensor | None:
335  """Get the sensor for providing the value."""
336  if self.coordinator.data.extra_meter is None:
337  return None
338 
339  return getattr(self.coordinator.data.extra_meter, f"_{self._type}", None)
340 
341 
343  """The Youless extra meter power value sensor (s0)."""
344 
345  _attr_native_unit_of_measurement = UnitOfPower.WATT
346  _attr_device_class = SensorDeviceClass.POWER
347  _attr_state_class = SensorStateClass.MEASUREMENT
348 
349  def __init__(
350  self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, dev_type: str
351  ) -> None:
352  """Instantiate an extra meter power sensor."""
353  super().__init__(
354  coordinator, device, "extra", "Extra meter", f"extra_{dev_type}"
355  )
356  self._type_type = dev_type
357  self._attr_name_attr_name = f"Extra {dev_type}"
358 
359  @property
360  def get_sensor(self) -> YoulessSensor | None:
361  """Get the sensor for providing the value."""
362  if self.coordinator.data.extra_meter is None:
363  return None
364 
365  return getattr(self.coordinator.data.extra_meter, f"_{self._type}", None)
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device)
Definition: sensor.py:165
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, str dev_type)
Definition: sensor.py:186
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, str dev_type, SensorStateClass state_class)
Definition: sensor.py:216
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, str dev_type)
Definition: sensor.py:351
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, str dev_type)
Definition: sensor.py:325
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device)
Definition: sensor.py:144
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, int phase)
Definition: sensor.py:298
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, int phase)
Definition: sensor.py:244
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, int phase)
Definition: sensor.py:271
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device)
Definition: sensor.py:123
None __init__(self, DataUpdateCoordinator[YoulessAPI] coordinator, str device, str device_group, str friendly_name, str sensor_id)
Definition: sensor.py:84
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:36