From cb011570e81c2e9fcbf39e30b76dd9f441ce5264 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 21 Mar 2022 18:20:17 -1000 Subject: [PATCH] Seperate emonitor extra_state_attributes into their own sensors (#68479) --- homeassistant/components/emonitor/sensor.py | 91 ++++++++++++--------- 1 file changed, 52 insertions(+), 39 deletions(-) diff --git a/homeassistant/components/emonitor/sensor.py b/homeassistant/components/emonitor/sensor.py index b99dd35093e..39a8c90f283 100644 --- a/homeassistant/components/emonitor/sensor.py +++ b/homeassistant/components/emonitor/sensor.py @@ -1,9 +1,12 @@ """Support for a Emonitor channel sensor.""" -from aioemonitor.monitor import EmonitorChannel +from __future__ import annotations + +from aioemonitor.monitor import EmonitorChannel, EmonitorStatus from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, + SensorEntityDescription, SensorStateClass, ) from homeassistant.config_entries import ConfigEntry @@ -21,6 +24,12 @@ from homeassistant.helpers.update_coordinator import ( from . import name_short_mac from .const import DOMAIN +SENSORS = ( + SensorEntityDescription(key="inst_power"), + SensorEntityDescription(key="avg_power", name="Average"), + SensorEntityDescription(key="max_power", name="Max"), +) + async def async_setup_entry( hass: HomeAssistant, @@ -30,7 +39,7 @@ async def async_setup_entry( """Set up entry.""" coordinator = hass.data[DOMAIN][config_entry.entry_id] channels = coordinator.data.channels - entities = [] + entities: list[EmonitorPowerSensor] = [] seen_channels = set() for channel_number, channel in channels.items(): seen_channels.add(channel_number) @@ -39,7 +48,10 @@ async def async_setup_entry( if channel.paired_with_channel in seen_channels: continue - entities.append(EmonitorPowerSensor(coordinator, channel_number)) + entities.extend( + EmonitorPowerSensor(coordinator, description, channel_number) + for description in SENSORS + ) async_add_entities(entities) @@ -51,59 +63,60 @@ class EmonitorPowerSensor(CoordinatorEntity, SensorEntity): _attr_native_unit_of_measurement = POWER_WATT _attr_state_class = SensorStateClass.MEASUREMENT - def __init__(self, coordinator: DataUpdateCoordinator, channel_number: int) -> None: + def __init__( + self, + coordinator: DataUpdateCoordinator, + description: SensorEntityDescription, + channel_number: int, + ) -> None: """Initialize the channel sensor.""" + self.entity_description = description self.channel_number = channel_number super().__init__(coordinator) - self._attr_unique_id = f"{self.mac_address}_{channel_number}" + mac_address = self.emonitor_status.network.mac_address + if description.name: + self._attr_name = f"{self.channel_data.label} {description.name}" + self._attr_unique_id = f"{mac_address}_{channel_number}_{description.key}" + else: + self._attr_name = self.channel_data.label + self._attr_unique_id = f"{mac_address}_{channel_number}" + self._attr_device_info = DeviceInfo( + connections={(dr.CONNECTION_NETWORK_MAC, mac_address)}, + manufacturer="Powerhouse Dynamics, Inc.", + name=name_short_mac(mac_address[-6:]), + sw_version=self.emonitor_status.hardware.firmware_version, + ) + + @property + def channels(self) -> dict[int, EmonitorChannel]: + """Return the channels dict.""" + channels: dict[int, EmonitorChannel] = self.emonitor_status.channels + return channels @property def channel_data(self) -> EmonitorChannel: - """Channel data.""" - return self.coordinator.data.channels[self.channel_number] + """Return the channel data.""" + return self.channels[self.channel_number] @property - def paired_channel_data(self) -> EmonitorChannel: - """Channel data.""" - return self.coordinator.data.channels[self.channel_data.paired_with_channel] - - @property - def name(self) -> str: - """Name of the sensor.""" - return self.channel_data.label + def emonitor_status(self) -> EmonitorStatus: + """Return the EmonitorStatus.""" + return self.coordinator.data def _paired_attr(self, attr_name: str) -> float: """Cumulative attributes for channel and paired channel.""" - attr_val = getattr(self.channel_data, attr_name) - if self.channel_data.paired_with_channel: - attr_val += getattr(self.paired_channel_data, attr_name) + channel_data = self.channels[self.channel_number] + attr_val = getattr(channel_data, attr_name) + if paired_channel := channel_data.paired_with_channel: + attr_val += getattr(self.channels[paired_channel], attr_name) return attr_val @property def native_value(self) -> StateType: """State of the sensor.""" - return self._paired_attr("inst_power") + return self._paired_attr(self.entity_description.key) @property def extra_state_attributes(self) -> dict: """Return the device specific state attributes.""" - return { - "channel": self.channel_number, - "avg_power": self._paired_attr("avg_power"), - "max_power": self._paired_attr("max_power"), - } - - @property - def mac_address(self) -> str: - """Return the mac address of the device.""" - return self.coordinator.data.network.mac_address - - @property - def device_info(self) -> DeviceInfo: - """Return info about the emonitor device.""" - return DeviceInfo( - connections={(dr.CONNECTION_NETWORK_MAC, self.mac_address)}, - manufacturer="Powerhouse Dynamics, Inc.", - name=name_short_mac(self.mac_address[-6:]), - sw_version=self.coordinator.data.hardware.firmware_version, - ) + return {"channel": self.channel_number}