"""Discovergy sensor entity.""" from dataclasses import dataclass, field from pydiscovergy.models import Meter from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, SensorEntityDescription, SensorStateClass, ) from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_IDENTIFIERS, ATTR_MANUFACTURER, ATTR_MODEL, ATTR_NAME, UnitOfElectricPotential, UnitOfEnergy, UnitOfPower, UnitOfVolume, ) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import DiscovergyData, DiscovergyUpdateCoordinator from .const import DOMAIN, MANUFACTURER PARALLEL_UPDATES = 1 @dataclass class DiscovergyMixin: """Mixin for alternative keys.""" alternative_keys: list[str] = field(default_factory=lambda: []) scale: int = field(default_factory=lambda: 1000) @dataclass class DiscovergySensorEntityDescription(DiscovergyMixin, SensorEntityDescription): """Define Sensor entity description class.""" GAS_SENSORS: tuple[DiscovergySensorEntityDescription, ...] = ( DiscovergySensorEntityDescription( key="volume", translation_key="total_gas_consumption", suggested_display_precision=4, native_unit_of_measurement=UnitOfVolume.CUBIC_METERS, device_class=SensorDeviceClass.GAS, state_class=SensorStateClass.TOTAL_INCREASING, ), ) ELECTRICITY_SENSORS: tuple[DiscovergySensorEntityDescription, ...] = ( # power sensors DiscovergySensorEntityDescription( key="power", translation_key="total_power", native_unit_of_measurement=UnitOfPower.WATT, suggested_display_precision=3, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, ), DiscovergySensorEntityDescription( key="power1", translation_key="phase_1_power", native_unit_of_measurement=UnitOfPower.WATT, suggested_display_precision=3, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, alternative_keys=["phase1Power"], ), DiscovergySensorEntityDescription( key="power2", translation_key="phase_2_power", native_unit_of_measurement=UnitOfPower.WATT, suggested_display_precision=3, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, alternative_keys=["phase2Power"], ), DiscovergySensorEntityDescription( key="power3", translation_key="phase_3_power", native_unit_of_measurement=UnitOfPower.WATT, suggested_display_precision=3, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, alternative_keys=["phase3Power"], ), # voltage sensors DiscovergySensorEntityDescription( key="phase1Voltage", translation_key="phase_1_voltage", native_unit_of_measurement=UnitOfElectricPotential.VOLT, suggested_display_precision=1, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, ), DiscovergySensorEntityDescription( key="phase2Voltage", translation_key="phase_2_voltage", native_unit_of_measurement=UnitOfElectricPotential.VOLT, suggested_display_precision=1, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, ), DiscovergySensorEntityDescription( key="phase3Voltage", translation_key="phase_3_voltage", native_unit_of_measurement=UnitOfElectricPotential.VOLT, suggested_display_precision=1, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, ), # energy sensors DiscovergySensorEntityDescription( key="energy", translation_key="total_consumption", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, suggested_display_precision=4, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, scale=10000000000, ), DiscovergySensorEntityDescription( key="energyOut", translation_key="total_production", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, suggested_display_precision=4, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, scale=10000000000, ), ) async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up the Discovergy sensors.""" data: DiscovergyData = hass.data[DOMAIN][entry.entry_id] meters: list[Meter] = data.meters # always returns a list entities: list[DiscovergySensor] = [] for meter in meters: meter_id = meter.get_meter_id() sensors = None if meter.measurement_type == "ELECTRICITY": sensors = ELECTRICITY_SENSORS elif meter.measurement_type == "GAS": sensors = GAS_SENSORS if sensors is not None: for description in sensors: # check if this meter has this data, then add this sensor for key in {description.key, *description.alternative_keys}: coordinator: DiscovergyUpdateCoordinator = data.coordinators[ meter_id ] if key in coordinator.data.values: entities.append( DiscovergySensor(key, description, meter, coordinator) ) async_add_entities(entities, False) class DiscovergySensor(CoordinatorEntity[DiscovergyUpdateCoordinator], SensorEntity): """Represents a discovergy smart meter sensor.""" entity_description: DiscovergySensorEntityDescription data_key: str _attr_has_entity_name = True def __init__( self, data_key: str, description: DiscovergySensorEntityDescription, meter: Meter, coordinator: DiscovergyUpdateCoordinator, ) -> None: """Initialize the sensor.""" super().__init__(coordinator) self.data_key = data_key self.entity_description = description self._attr_unique_id = f"{meter.full_serial_number}-{data_key}" self._attr_device_info = { ATTR_IDENTIFIERS: {(DOMAIN, meter.get_meter_id())}, ATTR_NAME: f"{meter.measurement_type.capitalize()} {meter.location.street} {meter.location.street_number}", ATTR_MODEL: f"{meter.type} {meter.full_serial_number}", ATTR_MANUFACTURER: MANUFACTURER, } @property def native_value(self) -> StateType: """Return the sensor state.""" return float( self.coordinator.data.values[self.data_key] / self.entity_description.scale )