From 11a81dc4854dc3ae985b4c570bfcef8db7711979 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Mon, 16 Jan 2023 11:22:46 +0100 Subject: [PATCH] Improve typing of HomeWizard sensors (#85997) * Improve typing of HomeWizard sensors * Fix typo when tried to fix a typo :) --- homeassistant/components/homewizard/sensor.py | 184 +++++++++++------- tests/components/homewizard/generator.py | 4 +- 2 files changed, 117 insertions(+), 71 deletions(-) diff --git a/homeassistant/components/homewizard/sensor.py b/homeassistant/components/homewizard/sensor.py index fa00e112ea4..afe2917ad27 100644 --- a/homeassistant/components/homewizard/sensor.py +++ b/homeassistant/components/homewizard/sensor.py @@ -1,7 +1,11 @@ -"""Creates Homewizard sensor entities.""" +"""Creates HomeWizard sensor entities.""" from __future__ import annotations -from typing import Final, cast +from collections.abc import Callable +from dataclasses import dataclass +from typing import Final + +from homewizard_energy.models import Data from homeassistant.components.sensor import ( SensorDeviceClass, @@ -22,39 +26,57 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.typing import StateType -from .const import DOMAIN, DeviceResponseEntry +from .const import DOMAIN from .coordinator import HWEnergyDeviceUpdateCoordinator from .entity import HomeWizardEntity PARALLEL_UPDATES = 1 -SENSORS: Final[tuple[SensorEntityDescription, ...]] = ( - SensorEntityDescription( + +@dataclass +class HomeWizardEntityDescriptionMixin: + """Mixin values for HomeWizard entities.""" + + value_fn: Callable[[Data], float | int | str | None] + + +@dataclass +class HomeWizardSensorEntityDescription( + SensorEntityDescription, HomeWizardEntityDescriptionMixin +): + """Class describing HomeWizard sensor entities.""" + + +SENSORS: Final[tuple[HomeWizardSensorEntityDescription, ...]] = ( + HomeWizardSensorEntityDescription( key="smr_version", name="DSMR version", icon="mdi:counter", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.smr_version, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="meter_model", name="Smart meter model", icon="mdi:gauge", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.meter_model, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="wifi_ssid", name="Wi-Fi SSID", icon="mdi:wifi", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.wifi_ssid, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_tariff", name="Active tariff", icon="mdi:calendar-clock", + value_fn=lambda data: data.active_tariff, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="wifi_strength", name="Wi-Fi strength", icon="mdi:wifi", @@ -62,242 +84,277 @@ SENSORS: Final[tuple[SensorEntityDescription, ...]] = ( state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, + value_fn=lambda data: data.wifi_strength, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_import_kwh", name="Total power import", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_import_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_import_t1_kwh", name="Total power import T1", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_import_t1_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_import_t2_kwh", name="Total power import T2", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_import_t2_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_import_t3_kwh", name="Total power import T3", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_import_t3_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_import_t4_kwh", name="Total power import T4", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_import_t4_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_export_kwh", name="Total power export", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_export_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_export_t1_kwh", name="Total power export T1", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_export_t1_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_export_t2_kwh", name="Total power export T2", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_export_t2_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_export_t3_kwh", name="Total power export T3", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_export_t3_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_power_export_t4_kwh", name="Total power export T4", native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_power_export_t4_kwh, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_power_w", name="Active power", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda data: data.active_power_w, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_power_l1_w", name="Active power L1", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda data: data.active_power_l1_w, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_power_l2_w", name="Active power L2", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda data: data.active_power_l2_w, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_power_l3_w", name="Active power L3", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda data: data.active_power_l3_w, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_voltage_l1_v", name="Active voltage L1", native_unit_of_measurement=UnitOfElectricPotential.VOLT, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, + value_fn=lambda data: data.active_voltage_l1_v, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_voltage_l2_v", name="Active voltage L2", native_unit_of_measurement=UnitOfElectricPotential.VOLT, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, + value_fn=lambda data: data.active_voltage_l2_v, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_voltage_l3_v", name="Active voltage L3", native_unit_of_measurement=UnitOfElectricPotential.VOLT, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, + value_fn=lambda data: data.active_voltage_l3_v, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_current_l1_a", name="Active current L1", native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, device_class=SensorDeviceClass.CURRENT, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, + value_fn=lambda data: data.active_current_l1_a, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_current_l2_a", name="Active current L2", native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, device_class=SensorDeviceClass.CURRENT, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, + value_fn=lambda data: data.active_current_l2_a, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_current_l3_a", name="Active current L3", native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, device_class=SensorDeviceClass.CURRENT, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, + value_fn=lambda data: data.active_current_l3_a, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_frequency_hz", name="Active frequency", native_unit_of_measurement=UnitOfFrequency.HERTZ, device_class=SensorDeviceClass.FREQUENCY, state_class=SensorStateClass.MEASUREMENT, entity_registry_enabled_default=False, + value_fn=lambda data: data.active_frequency_hz, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="voltage_sag_l1_count", name="Voltage sags detected L1", icon="mdi:alert", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.voltage_sag_l1_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="voltage_sag_l2_count", name="Voltage sags detected L2", icon="mdi:alert", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.voltage_sag_l2_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="voltage_sag_l3_count", name="Voltage sags detected L3", icon="mdi:alert", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.voltage_sag_l3_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="voltage_swell_l1_count", name="Voltage swells detected L1", icon="mdi:alert", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.voltage_swell_l1_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="voltage_swell_l2_count", name="Voltage swells detected L2", icon="mdi:alert", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.voltage_swell_l2_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="voltage_swell_l3_count", name="Voltage swells detected L3", icon="mdi:alert", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.voltage_swell_l3_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="any_power_fail_count", name="Power failures detected", icon="mdi:transmission-tower-off", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.any_power_fail_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="long_power_fail_count", name="Long power failures detected", icon="mdi:transmission-tower-off", entity_category=EntityCategory.DIAGNOSTIC, + value_fn=lambda data: data.long_power_fail_count, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_power_average_w", name="Active average demand", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, + value_fn=lambda data: data.active_power_average_w, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="montly_power_peak_w", name="Peak demand current month", native_unit_of_measurement=UnitOfPower.WATT, device_class=SensorDeviceClass.POWER, + value_fn=lambda data: data.montly_power_peak_w, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_gas_m3", name="Total gas", native_unit_of_measurement=UnitOfVolume.CUBIC_METERS, device_class=SensorDeviceClass.GAS, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_gas_m3, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="active_liter_lpm", name="Active water usage", native_unit_of_measurement="l/min", icon="mdi:water", state_class=SensorStateClass.MEASUREMENT, + value_fn=lambda data: data.active_liter_lpm, ), - SensorEntityDescription( + HomeWizardSensorEntityDescription( key="total_liter_m3", name="Total water usage", native_unit_of_measurement=UnitOfVolume.CUBIC_METERS, icon="mdi:gauge", device_class=SensorDeviceClass.WATER, state_class=SensorStateClass.TOTAL_INCREASING, + value_fn=lambda data: data.total_liter_m3, ), ) @@ -308,39 +365,33 @@ async def async_setup_entry( """Initialize sensors.""" coordinator: HWEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] - entities: list[HWEnergySensor] = [] - if coordinator.data.data is not None: - entities.extend( - HWEnergySensor(coordinator, entry, description) - for description in SENSORS - if getattr(coordinator.data.data, description.key) is not None - ) - async_add_entities(entities) + async_add_entities( + HomeWizardSensorEntity(coordinator, entry, description) + for description in SENSORS + if description.value_fn(coordinator.data.data) is not None + ) -class HWEnergySensor(HomeWizardEntity, SensorEntity): +class HomeWizardSensorEntity(HomeWizardEntity, SensorEntity): """Representation of a HomeWizard Sensor.""" + entity_description: HomeWizardSensorEntityDescription + def __init__( self, coordinator: HWEnergyDeviceUpdateCoordinator, entry: ConfigEntry, - description: SensorEntityDescription, + description: HomeWizardSensorEntityDescription, ) -> None: """Initialize Sensor Domain.""" - super().__init__(coordinator) self.entity_description = description - self.entry = entry - - # Config attributes. - self.data_type = description.key self._attr_unique_id = f"{entry.unique_id}_{description.key}" - # Special case for export, not everyone has solarpanels + # Special case for export, not everyone has solar panels # The chance that 'export' is non-zero when you have solar panels is nil if ( - self.data_type + description.key in [ "total_power_export_kwh", "total_power_export_t1_kwh", @@ -353,14 +404,9 @@ class HWEnergySensor(HomeWizardEntity, SensorEntity): self._attr_entity_registry_enabled_default = False @property - def data(self) -> DeviceResponseEntry: - """Return data object from DataUpdateCoordinator.""" - return self.coordinator.data - - @property - def native_value(self) -> StateType: - """Return state of meter.""" - return cast(StateType, getattr(self.data.data, self.data_type)) + def native_value(self) -> float | int | str | None: + """Return the sensor value.""" + return self.entity_description.value_fn(self.coordinator.data.data) @property def available(self) -> bool: diff --git a/tests/components/homewizard/generator.py b/tests/components/homewizard/generator.py index dff1a4462d3..f9bdea74fb4 100644 --- a/tests/components/homewizard/generator.py +++ b/tests/components/homewizard/generator.py @@ -3,7 +3,7 @@ from unittest.mock import AsyncMock from homewizard_energy.features import Features -from homewizard_energy.models import Device +from homewizard_energy.models import Data, Device def get_mock_device( @@ -26,7 +26,7 @@ def get_mock_device( firmware_version=firmware_version, ) ) - mock_device.data = AsyncMock(return_value=None) + mock_device.data = AsyncMock(return_value=Data.from_dict({})) mock_device.state = AsyncMock(return_value=None) mock_device.system = AsyncMock(return_value=None) mock_device.features = AsyncMock(