From 70f10338cc3e648e72ba13c31c7a77b09527f42c Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 23 Sep 2021 18:29:58 +0200 Subject: [PATCH] Use EntityDescription - solaredge_local (#56434) --- .../components/solaredge_local/sensor.py | 382 ++++++++---------- 1 file changed, 172 insertions(+), 210 deletions(-) diff --git a/homeassistant/components/solaredge_local/sensor.py b/homeassistant/components/solaredge_local/sensor.py index 9d162e919f4..d3607ecd29c 100644 --- a/homeassistant/components/solaredge_local/sensor.py +++ b/homeassistant/components/solaredge_local/sensor.py @@ -1,6 +1,9 @@ """Support for SolarEdge-local Monitoring API.""" +from __future__ import annotations + from contextlib import suppress -from copy import deepcopy +from copy import copy +from dataclasses import dataclass from datetime import timedelta import logging import statistics @@ -9,7 +12,11 @@ from requests.exceptions import ConnectTimeout, HTTPError from solaredge_local import SolarEdge import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity +from homeassistant.components.sensor import ( + PLATFORM_SCHEMA, + SensorEntity, + SensorEntityDescription, +) from homeassistant.const import ( CONF_IP_ADDRESS, CONF_NAME, @@ -41,122 +48,134 @@ INVERTER_MODES = ( "IDLE", ) -# Supported sensor types: -# Key: ['json_key', 'name', unit, icon, attribute name] -SENSOR_TYPES = { - "current_AC_voltage": [ - "gridvoltage", - "Grid Voltage", - ELECTRIC_POTENTIAL_VOLT, - "mdi:current-ac", - None, - None, - ], - "current_DC_voltage": [ - "dcvoltage", - "DC Voltage", - ELECTRIC_POTENTIAL_VOLT, - "mdi:current-dc", - None, - None, - ], - "current_frequency": [ - "gridfrequency", - "Grid Frequency", - FREQUENCY_HERTZ, - "mdi:current-ac", - None, - None, - ], - "current_power": [ - "currentPower", - "Current Power", - POWER_WATT, - "mdi:solar-power", - None, - None, - ], - "energy_this_month": [ - "energyThisMonth", - "Energy This Month", - ENERGY_WATT_HOUR, - "mdi:solar-power", - None, - None, - ], - "energy_this_year": [ - "energyThisYear", - "Energy This Year", - ENERGY_WATT_HOUR, - "mdi:solar-power", - None, - None, - ], - "energy_today": [ - "energyToday", - "Energy Today", - ENERGY_WATT_HOUR, - "mdi:solar-power", - None, - None, - ], - "inverter_temperature": [ - "invertertemperature", - "Inverter Temperature", - TEMP_CELSIUS, - None, - "operating_mode", - DEVICE_CLASS_TEMPERATURE, - ], - "lifetime_energy": [ - "energyTotal", - "Lifetime Energy", - ENERGY_WATT_HOUR, - "mdi:solar-power", - None, - None, - ], - "optimizer_connected": [ - "optimizers", - "Optimizers Online", - "optimizers", - "mdi:solar-panel", - "optimizers_connected", - None, - ], - "optimizer_current": [ - "optimizercurrent", - "Average Optimizer Current", - ELECTRIC_CURRENT_AMPERE, - "mdi:solar-panel", - None, - None, - ], - "optimizer_power": [ - "optimizerpower", - "Average Optimizer Power", - POWER_WATT, - "mdi:solar-panel", - None, - None, - ], - "optimizer_temperature": [ - "optimizertemperature", - "Average Optimizer Temperature", - TEMP_CELSIUS, - "mdi:solar-panel", - None, - DEVICE_CLASS_TEMPERATURE, - ], - "optimizer_voltage": [ - "optimizervoltage", - "Average Optimizer Voltage", - ELECTRIC_POTENTIAL_VOLT, - "mdi:solar-panel", - None, - None, - ], -} + +@dataclass +class SolarEdgeLocalSensorEntityDescription(SensorEntityDescription): + """Describes SolarEdge-local sensor entity.""" + + extra_attribute: str | None = None + + +SENSOR_TYPES: tuple[SolarEdgeLocalSensorEntityDescription, ...] = ( + SolarEdgeLocalSensorEntityDescription( + key="gridvoltage", + name="Grid Voltage", + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + icon="mdi:current-ac", + ), + SolarEdgeLocalSensorEntityDescription( + key="dcvoltage", + name="DC Voltage", + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + icon="mdi:current-dc", + ), + SolarEdgeLocalSensorEntityDescription( + key="gridfrequency", + name="Grid Frequency", + native_unit_of_measurement=FREQUENCY_HERTZ, + icon="mdi:current-ac", + ), + SolarEdgeLocalSensorEntityDescription( + key="currentPower", + name="Current Power", + native_unit_of_measurement=POWER_WATT, + icon="mdi:solar-power", + ), + SolarEdgeLocalSensorEntityDescription( + key="energyThisMonth", + name="Energy This Month", + native_unit_of_measurement=ENERGY_WATT_HOUR, + icon="mdi:solar-power", + ), + SolarEdgeLocalSensorEntityDescription( + key="energyThisYear", + name="Energy This Year", + native_unit_of_measurement=ENERGY_WATT_HOUR, + icon="mdi:solar-power", + ), + SolarEdgeLocalSensorEntityDescription( + key="energyToday", + name="Energy Today", + native_unit_of_measurement=ENERGY_WATT_HOUR, + icon="mdi:solar-power", + ), + SolarEdgeLocalSensorEntityDescription( + key="energyTotal", + name="Lifetime Energy", + native_unit_of_measurement=ENERGY_WATT_HOUR, + icon="mdi:solar-power", + ), + SolarEdgeLocalSensorEntityDescription( + key="optimizers", + name="Optimizers Online", + native_unit_of_measurement="optimizers", + icon="mdi:solar-panel", + extra_attribute="optimizers_connected", + ), + SolarEdgeLocalSensorEntityDescription( + key="optimizercurrent", + name="Average Optimizer Current", + native_unit_of_measurement=ELECTRIC_CURRENT_AMPERE, + icon="mdi:solar-panel", + ), + SolarEdgeLocalSensorEntityDescription( + key="optimizerpower", + name="Average Optimizer Power", + native_unit_of_measurement=POWER_WATT, + icon="mdi:solar-panel", + ), + SolarEdgeLocalSensorEntityDescription( + key="optimizertemperature", + name="Average Optimizer Temperature", + native_unit_of_measurement=TEMP_CELSIUS, + icon="mdi:solar-panel", + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SolarEdgeLocalSensorEntityDescription( + key="optimizervoltage", + name="Average Optimizer Voltage", + native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, + icon="mdi:solar-panel", + ), +) + +SENSOR_TYPE_INVERTER_TEMPERATURE = SolarEdgeLocalSensorEntityDescription( + key="invertertemperature", + name="Inverter Temperature", + native_unit_of_measurement=TEMP_CELSIUS, + extra_attribute="operating_mode", + device_class=DEVICE_CLASS_TEMPERATURE, +) + +SENSOR_TYPES_ENERGY_IMPORT: tuple[SolarEdgeLocalSensorEntityDescription, ...] = ( + SolarEdgeLocalSensorEntityDescription( + key="currentPowerimport", + name="current import Power", + native_unit_of_measurement=POWER_WATT, + icon="mdi:arrow-collapse-down", + ), + SolarEdgeLocalSensorEntityDescription( + key="totalEnergyimport", + name="total import Energy", + native_unit_of_measurement=ENERGY_WATT_HOUR, + icon="mdi:counter", + ), +) + +SENSOR_TYPES_ENERGY_EXPORT: tuple[SolarEdgeLocalSensorEntityDescription, ...] = ( + SolarEdgeLocalSensorEntityDescription( + key="currentPowerexport", + name="current export Power", + native_unit_of_measurement=POWER_WATT, + icon="mdi:arrow-expand-up", + ), + SolarEdgeLocalSensorEntityDescription( + key="totalEnergyexport", + name="total export Energy", + native_unit_of_measurement=ENERGY_WATT_HOUR, + icon="mdi:counter", + ), +) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { @@ -188,133 +207,76 @@ def setup_platform(hass, config, add_entities, discovery_info=None): _LOGGER.error("Could not retrieve details from SolarEdge API") return + # Create solaredge data service which will retrieve and update the data. + data = SolarEdgeData(hass, api) + # Changing inverter temperature unit. - sensors = deepcopy(SENSOR_TYPES) + inverter_temp_description = copy(SENSOR_TYPE_INVERTER_TEMPERATURE) if status.inverters.primary.temperature.units.farenheit: - sensors["inverter_temperature"] = [ - "invertertemperature", - "Inverter Temperature", - TEMP_FAHRENHEIT, - "mdi:thermometer", - "operating_mode", - DEVICE_CLASS_TEMPERATURE, - ] + inverter_temp_description.native_unit_of_measurement = TEMP_FAHRENHEIT + + # Create entities + entities = [ + SolarEdgeSensor(platform_name, data, description) + for description in (*SENSOR_TYPES, inverter_temp_description) + ] try: if status.metersList[0]: - sensors["import_current_power"] = [ - "currentPowerimport", - "current import Power", - POWER_WATT, - "mdi:arrow-collapse-down", - None, - None, - ] - sensors["import_meter_reading"] = [ - "totalEnergyimport", - "total import Energy", - ENERGY_WATT_HOUR, - "mdi:counter", - None, - None, - ] + entities.extend( + [ + SolarEdgeSensor(platform_name, data, description) + for description in SENSOR_TYPES_ENERGY_IMPORT + ] + ) except IndexError: _LOGGER.debug("Import meter sensors are not created") try: if status.metersList[1]: - sensors["export_current_power"] = [ - "currentPowerexport", - "current export Power", - POWER_WATT, - "mdi:arrow-expand-up", - None, - None, - ] - sensors["export_meter_reading"] = [ - "totalEnergyexport", - "total export Energy", - ENERGY_WATT_HOUR, - "mdi:counter", - None, - None, - ] + entities.extend( + [ + SolarEdgeSensor(platform_name, data, description) + for description in SENSOR_TYPES_ENERGY_EXPORT + ] + ) except IndexError: _LOGGER.debug("Export meter sensors are not created") - # Create solaredge data service which will retrieve and update the data. - data = SolarEdgeData(hass, api) - - # Create a new sensor for each sensor type. - entities = [] - for sensor_info in sensors.values(): - sensor = SolarEdgeSensor( - platform_name, - data, - sensor_info[0], - sensor_info[1], - sensor_info[2], - sensor_info[3], - sensor_info[4], - sensor_info[5], - ) - entities.append(sensor) - add_entities(entities, True) class SolarEdgeSensor(SensorEntity): """Representation of an SolarEdge Monitoring API sensor.""" + entity_description: SolarEdgeLocalSensorEntityDescription + def __init__( - self, platform_name, data, json_key, name, unit, icon, attr, device_class + self, + platform_name, + data, + description: SolarEdgeLocalSensorEntityDescription, ): """Initialize the sensor.""" + self.entity_description = description self._platform_name = platform_name self._data = data - self._state = None - - self._json_key = json_key - self._name = name - self._unit_of_measurement = unit - self._icon = icon - self._attr = attr - self._attr_device_class = device_class - - @property - def name(self): - """Return the name.""" - return f"{self._platform_name} ({self._name})" - - @property - def native_unit_of_measurement(self): - """Return the unit of measurement.""" - return self._unit_of_measurement + self._attr_name = f"{platform_name} ({description.name})" @property def extra_state_attributes(self): """Return the state attributes.""" - if self._attr: + if extra_attr := self.entity_description.extra_attribute: try: - return {self._attr: self._data.info[self._json_key]} + return {extra_attr: self._data.info[self.entity_description.key]} except KeyError: - return None + pass return None - @property - def icon(self): - """Return the sensor icon.""" - return self._icon - - @property - def native_value(self): - """Return the state of the sensor.""" - return self._state - def update(self): """Get the latest data from the sensor and update the state.""" self._data.update() - self._state = self._data.data[self._json_key] + self._attr_native_value = self._data.data[self.entity_description.key] class SolarEdgeData: