Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for a Emonitor channel sensor."""
2 
3 from __future__ import annotations
4 
5 from aioemonitor.monitor import EmonitorChannel, EmonitorStatus
6 
8  SensorDeviceClass,
9  SensorEntity,
10  SensorEntityDescription,
11  SensorStateClass,
12 )
13 from homeassistant.const import UnitOfPower
14 from homeassistant.core import HomeAssistant, callback
15 from homeassistant.helpers import device_registry as dr
16 from homeassistant.helpers.device_registry import DeviceInfo
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19  CoordinatorEntity,
20  DataUpdateCoordinator,
21 )
22 
23 from . import EmonitorConfigEntry, name_short_mac
24 
25 SENSORS = (
26  SensorEntityDescription(key="inst_power"),
28  key="avg_power",
29  translation_key="average",
30  entity_registry_enabled_default=False,
31  ),
33  key="max_power", translation_key="max", entity_registry_enabled_default=False
34  ),
35 )
36 
37 
39  hass: HomeAssistant,
40  config_entry: EmonitorConfigEntry,
41  async_add_entities: AddEntitiesCallback,
42 ) -> None:
43  """Set up entry."""
44  coordinator = config_entry.runtime_data
45  channels = coordinator.data.channels
46  entities: list[EmonitorPowerSensor] = []
47  seen_channels = set()
48  for channel_number, channel in channels.items():
49  seen_channels.add(channel_number)
50  if not channel.active:
51  continue
52  if channel.paired_with_channel in seen_channels:
53  continue
54 
55  entities.extend(
56  EmonitorPowerSensor(coordinator, description, channel_number)
57  for description in SENSORS
58  )
59 
60  async_add_entities(entities)
61 
62 
63 class EmonitorPowerSensor(CoordinatorEntity[EmonitorStatus], SensorEntity):
64  """Representation of an Emonitor power sensor entity."""
65 
66  _attr_device_class = SensorDeviceClass.POWER
67  _attr_native_unit_of_measurement = UnitOfPower.WATT
68  _attr_state_class = SensorStateClass.MEASUREMENT
69  _attr_has_entity_name = True
70 
71  def __init__(
72  self,
73  coordinator: DataUpdateCoordinator,
74  description: SensorEntityDescription,
75  channel_number: int,
76  ) -> None:
77  """Initialize the channel sensor."""
78  self.entity_descriptionentity_description = description
79  self.channel_numberchannel_number = channel_number
80  super().__init__(coordinator)
81  emonitor_status = self.coordinator.data
82  mac_address = emonitor_status.network.mac_address
83  device_name = name_short_mac(mac_address[-6:])
84  label = self.channel_datachannel_data.label or str(channel_number)
85  if description.translation_key is not None:
86  self._attr_translation_placeholders_attr_translation_placeholders = {"label": label}
87  self._attr_unique_id_attr_unique_id = f"{mac_address}_{channel_number}_{description.key}"
88  else:
89  self._attr_name_attr_name = label
90  self._attr_unique_id_attr_unique_id = f"{mac_address}_{channel_number}"
91  self._attr_device_info_attr_device_info = DeviceInfo(
92  connections={(dr.CONNECTION_NETWORK_MAC, mac_address)},
93  manufacturer="Powerhouse Dynamics, Inc.",
94  name=device_name,
95  sw_version=emonitor_status.hardware.firmware_version,
96  )
97  self._attr_extra_state_attributes_attr_extra_state_attributes = {"channel": channel_number}
98  self._attr_native_value_attr_native_value = self._paired_attr_paired_attr(self.entity_descriptionentity_description.key)
99 
100  @property
101  def channels(self) -> dict[int, EmonitorChannel]:
102  """Return the channels dict."""
103  channels: dict[int, EmonitorChannel] = self.coordinator.data.channels
104  return channels
105 
106  @property
107  def channel_data(self) -> EmonitorChannel:
108  """Return the channel data."""
109  return self.channelschannels[self.channel_numberchannel_number]
110 
111  def _paired_attr(self, attr_name: str) -> float:
112  """Cumulative attributes for channel and paired channel."""
113  channel_data = self.channelschannels[self.channel_numberchannel_number]
114  attr_val = getattr(channel_data, attr_name)
115  if paired_channel := channel_data.paired_with_channel:
116  attr_val += getattr(self.channelschannels[paired_channel], attr_name)
117  return attr_val
118 
119  @callback
120  def _handle_coordinator_update(self) -> None:
121  """Handle updated data from the coordinator."""
122  self._attr_native_value_attr_native_value = self._paired_attr_paired_attr(self.entity_descriptionentity_description.key)
123  return super()._handle_coordinator_update()
None __init__(self, DataUpdateCoordinator coordinator, SensorEntityDescription description, int channel_number)
Definition: sensor.py:76
None async_setup_entry(HomeAssistant hass, EmonitorConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:42