From 3f16c6d6efad20b60a4a8d2114a0905ecd252820 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 25 Feb 2022 09:20:56 -1000 Subject: [PATCH] Fix powerwall data incompatibility with energy integration (#67245) --- homeassistant/components/powerwall/sensor.py | 87 ++++++++++++++------ 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/homeassistant/components/powerwall/sensor.py b/homeassistant/components/powerwall/sensor.py index a48726211b2..bc8ab1c0215 100644 --- a/homeassistant/components/powerwall/sensor.py +++ b/homeassistant/components/powerwall/sensor.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import Any -from tesla_powerwall import MeterType +from tesla_powerwall import Meter, MeterType from homeassistant.components.sensor import ( SensorDeviceClass, @@ -28,7 +28,6 @@ from .models import PowerwallData, PowerwallRuntimeData _METER_DIRECTION_EXPORT = "export" _METER_DIRECTION_IMPORT = "import" -_METER_DIRECTIONS = [_METER_DIRECTION_EXPORT, _METER_DIRECTION_IMPORT] async def async_setup_entry( @@ -42,20 +41,20 @@ async def async_setup_entry( assert coordinator is not None data: PowerwallData = coordinator.data entities: list[ - PowerWallEnergySensor | PowerWallEnergyDirectionSensor | PowerWallChargeSensor - ] = [] - for meter in data.meters.meters: - entities.append(PowerWallEnergySensor(powerwall_data, meter)) - for meter_direction in _METER_DIRECTIONS: - entities.append( - PowerWallEnergyDirectionSensor( - powerwall_data, - meter, - meter_direction, - ) - ) + PowerWallEnergySensor + | PowerWallImportSensor + | PowerWallExportSensor + | PowerWallChargeSensor + ] = [PowerWallChargeSensor(powerwall_data)] - entities.append(PowerWallChargeSensor(powerwall_data)) + for meter in data.meters.meters: + entities.extend( + [ + PowerWallEnergySensor(powerwall_data, meter), + PowerWallExportSensor(powerwall_data, meter), + PowerWallImportSensor(powerwall_data, meter), + ] + ) async_add_entities(entities) @@ -128,18 +127,54 @@ class PowerWallEnergyDirectionSensor(PowerWallEntity, SensorEntity): """Initialize the sensor.""" super().__init__(powerwall_data) self._meter = meter - self._meter_direction = meter_direction - self._attr_name = ( - f"Powerwall {self._meter.value.title()} {self._meter_direction.title()}" - ) - self._attr_unique_id = ( - f"{self.base_unique_id}_{self._meter.value}_{self._meter_direction}" - ) + self._attr_name = f"Powerwall {meter.value.title()} {meter_direction.title()}" + self._attr_unique_id = f"{self.base_unique_id}_{meter.value}_{meter_direction}" + + @property + def available(self) -> bool: + """Check if the reading is actually available. + + The device reports 0 when something goes wrong which + we do not want to include in statistics and its a + transient data error. + """ + return super().available and self.native_value != 0 + + @property + def meter(self) -> Meter: + """Get the meter for the sensor.""" + return self.data.meters.get_meter(self._meter) + + +class PowerWallExportSensor(PowerWallEnergyDirectionSensor): + """Representation of an Powerwall Export sensor.""" + + def __init__( + self, + powerwall_data: PowerwallRuntimeData, + meter: MeterType, + ) -> None: + """Initialize the sensor.""" + super().__init__(powerwall_data, meter, _METER_DIRECTION_EXPORT) @property def native_value(self) -> float: """Get the current value in kWh.""" - meter = self.data.meters.get_meter(self._meter) - if self._meter_direction == _METER_DIRECTION_EXPORT: - return meter.get_energy_exported() - return meter.get_energy_imported() + return abs(self.meter.get_energy_exported()) + + +class PowerWallImportSensor(PowerWallEnergyDirectionSensor): + """Representation of an Powerwall Import sensor.""" + + def __init__( + self, + powerwall_data: PowerwallRuntimeData, + meter: MeterType, + ) -> None: + """Initialize the sensor.""" + super().__init__(powerwall_data, meter, _METER_DIRECTION_IMPORT) + + @property + def native_value(self) -> float: + """Get the current value in kWh.""" + return abs(self.meter.get_energy_imported())