diff --git a/homeassistant/components/youless/__init__.py b/homeassistant/components/youless/__init__.py index d475034cc9d..03a27b5a378 100644 --- a/homeassistant/components/youless/__init__.py +++ b/homeassistant/components/youless/__init__.py @@ -1,6 +1,5 @@ """The youless integration.""" -from datetime import timedelta import logging from urllib.error import URLError @@ -10,9 +9,9 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, Platform from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import DOMAIN +from .coordinator import YouLessCoordinator PLATFORMS = [Platform.SENSOR] @@ -28,24 +27,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: except URLError as exception: raise ConfigEntryNotReady from exception - async def async_update_data() -> YoulessAPI: - """Fetch data from the API.""" - await hass.async_add_executor_job(api.update) - return api - - coordinator = DataUpdateCoordinator( - hass, - _LOGGER, - config_entry=entry, - name="youless_gateway", - update_method=async_update_data, - update_interval=timedelta(seconds=10), - ) - - await coordinator.async_config_entry_first_refresh() + youless_coordinator = YouLessCoordinator(hass, api) + await youless_coordinator.async_config_entry_first_refresh() hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][entry.entry_id] = coordinator + hass.data[DOMAIN][entry.entry_id] = youless_coordinator await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True diff --git a/homeassistant/components/youless/coordinator.py b/homeassistant/components/youless/coordinator.py new file mode 100644 index 00000000000..0be5e463689 --- /dev/null +++ b/homeassistant/components/youless/coordinator.py @@ -0,0 +1,25 @@ +"""The coordinator for the Youless integration.""" + +from datetime import timedelta +import logging + +from youless_api import YoulessAPI + +from homeassistant.core import HomeAssistant +from homeassistant.helpers.update_coordinator import DataUpdateCoordinator + +_LOGGER = logging.getLogger(__name__) + + +class YouLessCoordinator(DataUpdateCoordinator[None]): + """Class to manage fetching YouLess data.""" + + def __init__(self, hass: HomeAssistant, device: YoulessAPI) -> None: + """Initialize global YouLess data provider.""" + super().__init__( + hass, _LOGGER, name="youless_gateway", update_interval=timedelta(seconds=10) + ) + self.device = device + + async def _async_update_data(self) -> None: + await self.hass.async_add_executor_job(self.device.update) diff --git a/homeassistant/components/youless/entity.py b/homeassistant/components/youless/entity.py new file mode 100644 index 00000000000..9931768c267 --- /dev/null +++ b/homeassistant/components/youless/entity.py @@ -0,0 +1,25 @@ +"""The entity for the Youless integration.""" + +from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from .const import DOMAIN +from .coordinator import YouLessCoordinator + + +class YouLessEntity(CoordinatorEntity[YouLessCoordinator]): + """Base entity for YouLess.""" + + def __init__( + self, coordinator: YouLessCoordinator, device_group: str, device_name: str + ) -> None: + """Initialize the entity.""" + super().__init__(coordinator) + self.device = coordinator.device + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, device_group)}, + manufacturer="YouLess", + model=self.device.model, + name=device_name, + sw_version=self.device.firmware_version, + ) diff --git a/homeassistant/components/youless/sensor.py b/homeassistant/components/youless/sensor.py index ed0fc703cc4..413f1ad6958 100644 --- a/homeassistant/components/youless/sensor.py +++ b/homeassistant/components/youless/sensor.py @@ -2,12 +2,15 @@ from __future__ import annotations +from collections.abc import Callable +from dataclasses import dataclass + from youless_api import YoulessAPI -from youless_api.youless_sensor import YoulessSensor from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, + SensorEntityDescription, SensorStateClass, ) from homeassistant.config_entries import ConfigEntry @@ -20,346 +23,316 @@ from homeassistant.const import ( UnitOfVolume, ) from homeassistant.core import HomeAssistant -from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, -) from . import DOMAIN +from .coordinator import YouLessCoordinator +from .entity import YouLessEntity + + +@dataclass(frozen=True, kw_only=True) +class YouLessSensorEntityDescription(SensorEntityDescription): + """Describes a YouLess sensor entity.""" + + device_group: str + device_group_name: str + value_func: Callable[[YoulessAPI], float | None] + + +SENSOR_TYPES: tuple[YouLessSensorEntityDescription, ...] = ( + YouLessSensorEntityDescription( + key="water", + device_group="water", + device_group_name="Water meter", + name="Water usage", + icon="mdi:water", + device_class=SensorDeviceClass.WATER, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfVolume.CUBIC_METERS, + value_func=( + lambda device: device.water_meter.value if device.water_meter else None + ), + ), + YouLessSensorEntityDescription( + key="gas", + device_group="gas", + device_group_name="Gas meter", + name="Gas usage", + icon="mdi:fire", + device_class=SensorDeviceClass.GAS, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfVolume.CUBIC_METERS, + value_func=lambda device: device.gas_meter.value if device.gas_meter else None, + ), + YouLessSensorEntityDescription( + key="usage", + device_group="power", + device_group_name="Power usage", + name="Power Usage", + icon="mdi:meter-electric", + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfPower.WATT, + value_func=( + lambda device: device.current_power_usage.value + if device.current_power_usage + else None + ), + ), + YouLessSensorEntityDescription( + key="power_low", + device_group="power", + device_group_name="Power usage", + name="Energy low", + icon="mdi:transmission-tower-export", + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_func=( + lambda device: device.power_meter.low.value if device.power_meter else None + ), + ), + YouLessSensorEntityDescription( + key="power_high", + device_group="power", + device_group_name="Power usage", + name="Energy high", + icon="mdi:transmission-tower-export", + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_func=( + lambda device: device.power_meter.high.value if device.power_meter else None + ), + ), + YouLessSensorEntityDescription( + key="power_total", + device_group="power", + device_group_name="Power usage", + name="Energy total", + icon="mdi:transmission-tower-export", + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_func=( + lambda device: device.power_meter.total.value + if device.power_meter + else None + ), + ), + YouLessSensorEntityDescription( + key="phase_1_power", + device_group="power", + device_group_name="Power usage", + name="Phase 1 power", + icon=None, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfPower.WATT, + value_func=lambda device: device.phase1.power.value if device.phase1 else None, + ), + YouLessSensorEntityDescription( + key="phase_1_voltage", + device_group="power", + device_group_name="Power usage", + name="Phase 1 voltage", + icon=None, + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfElectricPotential.VOLT, + value_func=( + lambda device: device.phase1.voltage.value if device.phase1 else None + ), + ), + YouLessSensorEntityDescription( + key="phase_1_current", + device_group="power", + device_group_name="Power usage", + name="Phase 1 current", + icon=None, + device_class=SensorDeviceClass.CURRENT, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, + value_func=( + lambda device: device.phase1.current.value if device.phase1 else None + ), + ), + YouLessSensorEntityDescription( + key="phase_2_power", + device_group="power", + device_group_name="Power usage", + name="Phase 2 power", + icon=None, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfPower.WATT, + value_func=lambda device: device.phase2.power.value if device.phase2 else None, + ), + YouLessSensorEntityDescription( + key="phase_2_voltage", + device_group="power", + device_group_name="Power usage", + name="Phase 2 voltage", + icon=None, + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfElectricPotential.VOLT, + value_func=( + lambda device: device.phase2.voltage.value if device.phase2 else None + ), + ), + YouLessSensorEntityDescription( + key="phase_2_current", + device_group="power", + device_group_name="Power usage", + name="Phase 2 current", + icon=None, + device_class=SensorDeviceClass.CURRENT, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, + value_func=( + lambda device: device.phase2.current.value if device.phase1 else None + ), + ), + YouLessSensorEntityDescription( + key="phase_3_power", + device_group="power", + device_group_name="Power usage", + name="Phase 3 power", + icon=None, + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfPower.WATT, + value_func=lambda device: device.phase3.power.value if device.phase3 else None, + ), + YouLessSensorEntityDescription( + key="phase_3_voltage", + device_group="power", + device_group_name="Power usage", + name="Phase 3 voltage", + icon=None, + device_class=SensorDeviceClass.VOLTAGE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfElectricPotential.VOLT, + value_func=( + lambda device: device.phase3.voltage.value if device.phase3 else None + ), + ), + YouLessSensorEntityDescription( + key="phase_3_current", + device_group="power", + device_group_name="Power usage", + name="Phase 3 current", + icon=None, + device_class=SensorDeviceClass.CURRENT, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, + value_func=( + lambda device: device.phase3.current.value if device.phase1 else None + ), + ), + YouLessSensorEntityDescription( + key="delivery_low", + device_group="delivery", + device_group_name="Energy delivery", + name="Energy delivery low", + icon="mdi:transmission-tower-import", + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_func=( + lambda device: device.delivery_meter.low.value + if device.delivery_meter + else None + ), + ), + YouLessSensorEntityDescription( + key="delivery_high", + device_group="delivery", + device_group_name="Energy delivery", + name="Energy delivery high", + icon="mdi:transmission-tower-import", + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_func=( + lambda device: device.delivery_meter.high.value + if device.delivery_meter + else None + ), + ), + YouLessSensorEntityDescription( + key="extra_total", + device_group="extra", + device_group_name="Extra meter", + name="Extra total", + icon="mdi:meter-electric", + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_func=( + lambda device: device.extra_meter.total.value + if device.extra_meter + else None + ), + ), + YouLessSensorEntityDescription( + key="extra_usage", + device_group="extra", + device_group_name="Extra meter", + name="Extra usage", + icon="mdi:lightning-bolt", + device_class=SensorDeviceClass.POWER, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfPower.WATT, + value_func=( + lambda device: device.extra_meter.usage.value + if device.extra_meter + else None + ), + ), +) async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Initialize the integration.""" - coordinator: DataUpdateCoordinator[YoulessAPI] = hass.data[DOMAIN][entry.entry_id] + coordinator: YouLessCoordinator = hass.data[DOMAIN][entry.entry_id] device = entry.data[CONF_DEVICE] if (device := entry.data[CONF_DEVICE]) is None: device = entry.entry_id async_add_entities( [ - WaterSensor(coordinator, device), - GasSensor(coordinator, device), - EnergyMeterSensor( - coordinator, device, "low", SensorStateClass.TOTAL_INCREASING - ), - EnergyMeterSensor( - coordinator, device, "high", SensorStateClass.TOTAL_INCREASING - ), - EnergyMeterSensor(coordinator, device, "total", SensorStateClass.TOTAL), - CurrentPowerSensor(coordinator, device), - DeliveryMeterSensor(coordinator, device, "low"), - DeliveryMeterSensor(coordinator, device, "high"), - ExtraMeterSensor(coordinator, device, "total"), - ExtraMeterPowerSensor(coordinator, device, "usage"), - PhasePowerSensor(coordinator, device, 1), - PhaseVoltageSensor(coordinator, device, 1), - PhaseCurrentSensor(coordinator, device, 1), - PhasePowerSensor(coordinator, device, 2), - PhaseVoltageSensor(coordinator, device, 2), - PhaseCurrentSensor(coordinator, device, 2), - PhasePowerSensor(coordinator, device, 3), - PhaseVoltageSensor(coordinator, device, 3), - PhaseCurrentSensor(coordinator, device, 3), + YouLessSensor(coordinator, description, device) + for description in SENSOR_TYPES ] ) -class YoulessBaseSensor( - CoordinatorEntity[DataUpdateCoordinator[YoulessAPI]], SensorEntity -): - """The base sensor for Youless.""" +class YouLessSensor(YouLessEntity, SensorEntity): + """Representation of a Sensor.""" + + entity_description: YouLessSensorEntityDescription def __init__( self, - coordinator: DataUpdateCoordinator[YoulessAPI], + coordinator: YouLessCoordinator, + description: YouLessSensorEntityDescription, device: str, - device_group: str, - friendly_name: str, - sensor_id: str, ) -> None: - """Create the sensor.""" - super().__init__(coordinator) - self._attr_unique_id = f"{DOMAIN}_{device}_{sensor_id}" - self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, f"{device}_{device_group}")}, - manufacturer="YouLess", - model=self.coordinator.data.model, - name=friendly_name, + """Initialize the sensor.""" + super().__init__( + coordinator, + f"{device}_{description.device_group}", + description.device_group_name, ) - - @property - def get_sensor(self) -> YoulessSensor | None: - """Property to get the underlying sensor object.""" - return None + self._attr_unique_id = f"{DOMAIN}_{device}_{description.key}" + self.entity_description = description @property def native_value(self) -> StateType: - """Determine the state value, only if a sensor is initialized.""" - if self.get_sensor is None: - return None - - return self.get_sensor.value - - @property - def available(self) -> bool: - """Return a flag to indicate the sensor not being available.""" - return super().available and self.get_sensor is not None - - -class WaterSensor(YoulessBaseSensor): - """The Youless Water sensor.""" - - _attr_native_unit_of_measurement = UnitOfVolume.CUBIC_METERS - _attr_device_class = SensorDeviceClass.WATER - _attr_state_class = SensorStateClass.TOTAL_INCREASING - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str - ) -> None: - """Instantiate a Water sensor.""" - super().__init__(coordinator, device, "water", "Water meter", "water") - self._attr_name = "Water usage" - self._attr_icon = "mdi:water" - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor for providing the value.""" - return self.coordinator.data.water_meter - - -class GasSensor(YoulessBaseSensor): - """The Youless gas sensor.""" - - _attr_native_unit_of_measurement = UnitOfVolume.CUBIC_METERS - _attr_device_class = SensorDeviceClass.GAS - _attr_state_class = SensorStateClass.TOTAL_INCREASING - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str - ) -> None: - """Instantiate a gas sensor.""" - super().__init__(coordinator, device, "gas", "Gas meter", "gas") - self._attr_name = "Gas usage" - self._attr_icon = "mdi:fire" - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor for providing the value.""" - return self.coordinator.data.gas_meter - - -class CurrentPowerSensor(YoulessBaseSensor): - """The current power usage sensor.""" - - _attr_native_unit_of_measurement = UnitOfPower.WATT - _attr_device_class = SensorDeviceClass.POWER - _attr_state_class = SensorStateClass.MEASUREMENT - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str - ) -> None: - """Instantiate the usage meter.""" - super().__init__(coordinator, device, "power", "Power usage", "usage") - self._device = device - self._attr_name = "Power Usage" - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor for providing the value.""" - return self.coordinator.data.current_power_usage - - -class DeliveryMeterSensor(YoulessBaseSensor): - """The Youless delivery meter value sensor.""" - - _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR - _attr_device_class = SensorDeviceClass.ENERGY - _attr_state_class = SensorStateClass.TOTAL_INCREASING - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, dev_type: str - ) -> None: - """Instantiate a delivery meter sensor.""" - super().__init__( - coordinator, device, "delivery", "Energy delivery", f"delivery_{dev_type}" - ) - self._type = dev_type - self._attr_name = f"Energy delivery {dev_type}" - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor for providing the value.""" - if self.coordinator.data.delivery_meter is None: - return None - - return getattr(self.coordinator.data.delivery_meter, f"_{self._type}", None) - - -class EnergyMeterSensor(YoulessBaseSensor): - """The Youless low meter value sensor.""" - - _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR - _attr_device_class = SensorDeviceClass.ENERGY - _attr_state_class = SensorStateClass.TOTAL_INCREASING - - def __init__( - self, - coordinator: DataUpdateCoordinator[YoulessAPI], - device: str, - dev_type: str, - state_class: SensorStateClass, - ) -> None: - """Instantiate a energy meter sensor.""" - super().__init__( - coordinator, device, "power", "Energy usage", f"power_{dev_type}" - ) - self._device = device - self._type = dev_type - self._attr_name = f"Energy {dev_type}" - self._attr_state_class = state_class - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor for providing the value.""" - if self.coordinator.data.power_meter is None: - return None - - return getattr(self.coordinator.data.power_meter, f"_{self._type}", None) - - -class PhasePowerSensor(YoulessBaseSensor): - """The current power usage of a single phase.""" - - _attr_native_unit_of_measurement = UnitOfPower.WATT - _attr_device_class = SensorDeviceClass.POWER - _attr_state_class = SensorStateClass.MEASUREMENT - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, phase: int - ) -> None: - """Initialize the power phase sensor.""" - super().__init__( - coordinator, device, "power", "Energy usage", f"phase_{phase}_power" - ) - self._attr_name = f"Phase {phase} power" - self._phase = phase - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor value from the coordinator.""" - phase_sensor = getattr(self.coordinator.data, f"phase{self._phase}", None) - if phase_sensor is None: - return None - - return phase_sensor.power - - -class PhaseVoltageSensor(YoulessBaseSensor): - """The current voltage of a single phase.""" - - _attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT - _attr_device_class = SensorDeviceClass.VOLTAGE - _attr_state_class = SensorStateClass.MEASUREMENT - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, phase: int - ) -> None: - """Initialize the voltage phase sensor.""" - super().__init__( - coordinator, device, "power", "Energy usage", f"phase_{phase}_voltage" - ) - self._attr_name = f"Phase {phase} voltage" - self._phase = phase - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor value from the coordinator for phase voltage.""" - phase_sensor = getattr(self.coordinator.data, f"phase{self._phase}", None) - if phase_sensor is None: - return None - - return phase_sensor.voltage - - -class PhaseCurrentSensor(YoulessBaseSensor): - """The current current of a single phase.""" - - _attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE - _attr_device_class = SensorDeviceClass.CURRENT - _attr_state_class = SensorStateClass.MEASUREMENT - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, phase: int - ) -> None: - """Initialize the current phase sensor.""" - super().__init__( - coordinator, device, "power", "Energy usage", f"phase_{phase}_current" - ) - self._attr_name = f"Phase {phase} current" - self._phase = phase - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor value from the coordinator for phase current.""" - phase_sensor = getattr(self.coordinator.data, f"phase{self._phase}", None) - if phase_sensor is None: - return None - - return phase_sensor.current - - -class ExtraMeterSensor(YoulessBaseSensor): - """The Youless extra meter value sensor (s0).""" - - _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR - _attr_device_class = SensorDeviceClass.ENERGY - _attr_state_class = SensorStateClass.TOTAL_INCREASING - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, dev_type: str - ) -> None: - """Instantiate an extra meter sensor.""" - super().__init__( - coordinator, device, "extra", "Extra meter", f"extra_{dev_type}" - ) - self._type = dev_type - self._attr_name = f"Extra {dev_type}" - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor for providing the value.""" - if self.coordinator.data.extra_meter is None: - return None - - return getattr(self.coordinator.data.extra_meter, f"_{self._type}", None) - - -class ExtraMeterPowerSensor(YoulessBaseSensor): - """The Youless extra meter power value sensor (s0).""" - - _attr_native_unit_of_measurement = UnitOfPower.WATT - _attr_device_class = SensorDeviceClass.POWER - _attr_state_class = SensorStateClass.MEASUREMENT - - def __init__( - self, coordinator: DataUpdateCoordinator[YoulessAPI], device: str, dev_type: str - ) -> None: - """Instantiate an extra meter power sensor.""" - super().__init__( - coordinator, device, "extra", "Extra meter", f"extra_{dev_type}" - ) - self._type = dev_type - self._attr_name = f"Extra {dev_type}" - - @property - def get_sensor(self) -> YoulessSensor | None: - """Get the sensor for providing the value.""" - if self.coordinator.data.extra_meter is None: - return None - - return getattr(self.coordinator.data.extra_meter, f"_{self._type}", None) + """Return the state of the sensor.""" + return self.entity_description.value_func(self.device) diff --git a/tests/components/youless/snapshots/test_sensor.ambr b/tests/components/youless/snapshots/test_sensor.ambr index bcfd0139e5c..3424a264f48 100644 --- a/tests/components/youless/snapshots/test_sensor.ambr +++ b/tests/components/youless/snapshots/test_sensor.ambr @@ -24,7 +24,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:transmission-tower-import', 'original_name': 'Energy delivery high', 'platform': 'youless', 'previous_unique_id': None, @@ -39,6 +39,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'energy', 'friendly_name': 'Energy delivery high', + 'icon': 'mdi:transmission-tower-import', 'state_class': , 'unit_of_measurement': , }), @@ -75,7 +76,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:transmission-tower-import', 'original_name': 'Energy delivery low', 'platform': 'youless', 'previous_unique_id': None, @@ -90,6 +91,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'energy', 'friendly_name': 'Energy delivery low', + 'icon': 'mdi:transmission-tower-import', 'state_class': , 'unit_of_measurement': , }), @@ -126,7 +128,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:transmission-tower-export', 'original_name': 'Energy high', 'platform': 'youless', 'previous_unique_id': None, @@ -141,6 +143,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'energy', 'friendly_name': 'Energy high', + 'icon': 'mdi:transmission-tower-export', 'state_class': , 'unit_of_measurement': , }), @@ -177,7 +180,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:transmission-tower-export', 'original_name': 'Energy low', 'platform': 'youless', 'previous_unique_id': None, @@ -192,6 +195,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'energy', 'friendly_name': 'Energy low', + 'icon': 'mdi:transmission-tower-export', 'state_class': , 'unit_of_measurement': , }), @@ -228,7 +232,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:transmission-tower-export', 'original_name': 'Energy total', 'platform': 'youless', 'previous_unique_id': None, @@ -243,6 +247,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'energy', 'friendly_name': 'Energy total', + 'icon': 'mdi:transmission-tower-export', 'state_class': , 'unit_of_measurement': , }), @@ -279,7 +284,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:meter-electric', 'original_name': 'Extra total', 'platform': 'youless', 'previous_unique_id': None, @@ -294,6 +299,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'energy', 'friendly_name': 'Extra total', + 'icon': 'mdi:meter-electric', 'state_class': , 'unit_of_measurement': , }), @@ -330,7 +336,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:lightning-bolt', 'original_name': 'Extra usage', 'platform': 'youless', 'previous_unique_id': None, @@ -345,6 +351,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'power', 'friendly_name': 'Extra usage', + 'icon': 'mdi:lightning-bolt', 'state_class': , 'unit_of_measurement': , }), @@ -456,7 +463,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_1_power-entry] @@ -507,7 +514,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_1_voltage-entry] @@ -558,7 +565,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_2_current-entry] @@ -609,7 +616,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_2_power-entry] @@ -660,7 +667,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_2_voltage-entry] @@ -711,7 +718,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_3_current-entry] @@ -762,7 +769,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_3_power-entry] @@ -813,7 +820,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.phase_3_voltage-entry] @@ -864,7 +871,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': 'unavailable', + 'state': 'unknown', }) # --- # name: test_sensors[sensor.power_usage-entry] @@ -892,7 +899,7 @@ 'options': dict({ }), 'original_device_class': , - 'original_icon': None, + 'original_icon': 'mdi:meter-electric', 'original_name': 'Power Usage', 'platform': 'youless', 'previous_unique_id': None, @@ -907,6 +914,7 @@ 'attributes': ReadOnlyDict({ 'device_class': 'power', 'friendly_name': 'Power Usage', + 'icon': 'mdi:meter-electric', 'state_class': , 'unit_of_measurement': , }),