mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Avoid mutating entity descriptions in sunweg (#105982)
This commit is contained in:
parent
27f81b3f63
commit
1d1cd6be57
@ -10,11 +10,10 @@ from homeassistant import config_entries
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType, UndefinedType
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
|
||||||
from .const import CONF_PLANT_ID, DOMAIN, PLATFORMS, DeviceType
|
from .const import CONF_PLANT_ID, DOMAIN, PLATFORMS, DeviceType
|
||||||
from .sensor_types.sensor_entity_description import SunWEGSensorEntityDescription
|
|
||||||
|
|
||||||
SCAN_INTERVAL = datetime.timedelta(minutes=5)
|
SCAN_INTERVAL = datetime.timedelta(minutes=5)
|
||||||
|
|
||||||
@ -102,24 +101,30 @@ class SunWEGData:
|
|||||||
|
|
||||||
def get_data(
|
def get_data(
|
||||||
self,
|
self,
|
||||||
entity_description: SunWEGSensorEntityDescription,
|
*,
|
||||||
|
api_variable_key: str,
|
||||||
|
api_variable_unit: str | None,
|
||||||
|
deep_name: str | None,
|
||||||
device_type: DeviceType,
|
device_type: DeviceType,
|
||||||
inverter_id: int = 0,
|
inverter_id: int,
|
||||||
deep_name: str | None = None,
|
name: str | UndefinedType | None,
|
||||||
) -> StateType | datetime.datetime:
|
native_unit_of_measurement: str | None,
|
||||||
|
never_resets: bool,
|
||||||
|
previous_value_drop_threshold: float | None,
|
||||||
|
) -> tuple[StateType | datetime.datetime, str | None]:
|
||||||
"""Get the data."""
|
"""Get the data."""
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Data request for: %s",
|
"Data request for: %s",
|
||||||
entity_description.name,
|
name,
|
||||||
)
|
)
|
||||||
variable = entity_description.api_variable_key
|
variable = api_variable_key
|
||||||
previous_unit = entity_description.native_unit_of_measurement
|
previous_unit = native_unit_of_measurement
|
||||||
api_value = self.get_api_value(variable, device_type, inverter_id, deep_name)
|
api_value = self.get_api_value(variable, device_type, inverter_id, deep_name)
|
||||||
previous_value = self.previous_values.get(variable)
|
previous_value = self.previous_values.get(variable)
|
||||||
return_value = api_value
|
return_value = api_value
|
||||||
if entity_description.api_variable_unit is not None:
|
if api_variable_unit is not None:
|
||||||
entity_description.native_unit_of_measurement = self.get_api_value(
|
native_unit_of_measurement = self.get_api_value(
|
||||||
entity_description.api_variable_unit,
|
api_variable_unit,
|
||||||
device_type,
|
device_type,
|
||||||
inverter_id,
|
inverter_id,
|
||||||
deep_name,
|
deep_name,
|
||||||
@ -127,18 +132,18 @@ class SunWEGData:
|
|||||||
|
|
||||||
# If we have a 'drop threshold' specified, then check it and correct if needed
|
# If we have a 'drop threshold' specified, then check it and correct if needed
|
||||||
if (
|
if (
|
||||||
entity_description.previous_value_drop_threshold is not None
|
previous_value_drop_threshold is not None
|
||||||
and previous_value is not None
|
and previous_value is not None
|
||||||
and api_value is not None
|
and api_value is not None
|
||||||
and previous_unit == entity_description.native_unit_of_measurement
|
and previous_unit == native_unit_of_measurement
|
||||||
):
|
):
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
(
|
(
|
||||||
"%s - Drop threshold specified (%s), checking for drop... API"
|
"%s - Drop threshold specified (%s), checking for drop... API"
|
||||||
" Value: %s, Previous Value: %s"
|
" Value: %s, Previous Value: %s"
|
||||||
),
|
),
|
||||||
entity_description.name,
|
name,
|
||||||
entity_description.previous_value_drop_threshold,
|
previous_value_drop_threshold,
|
||||||
api_value,
|
api_value,
|
||||||
previous_value,
|
previous_value,
|
||||||
)
|
)
|
||||||
@ -149,7 +154,7 @@ class SunWEGData:
|
|||||||
# Note - The energy dashboard takes care of drops within 10%
|
# Note - The energy dashboard takes care of drops within 10%
|
||||||
# of the current value, however if the value is low e.g. 0.2
|
# of the current value, however if the value is low e.g. 0.2
|
||||||
# and drops by 0.1 it classes as a reset.
|
# and drops by 0.1 it classes as a reset.
|
||||||
if -(entity_description.previous_value_drop_threshold) <= diff < 0:
|
if -(previous_value_drop_threshold) <= diff < 0:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
(
|
(
|
||||||
"Diff is negative, but only by a small amount therefore not a"
|
"Diff is negative, but only by a small amount therefore not a"
|
||||||
@ -161,9 +166,7 @@ class SunWEGData:
|
|||||||
)
|
)
|
||||||
return_value = previous_value
|
return_value = previous_value
|
||||||
else:
|
else:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug("%s - No drop detected, using API value", name)
|
||||||
"%s - No drop detected, using API value", entity_description.name
|
|
||||||
)
|
|
||||||
|
|
||||||
# Lifetime total values should always be increasing, they will never reset,
|
# Lifetime total values should always be increasing, they will never reset,
|
||||||
# however the API sometimes returns 0 values when the clock turns to 00:00
|
# however the API sometimes returns 0 values when the clock turns to 00:00
|
||||||
@ -178,7 +181,7 @@ class SunWEGData:
|
|||||||
# - Previous value will not exist meaning 0 will be returned
|
# - Previous value will not exist meaning 0 will be returned
|
||||||
# - This is an edge case that would be better handled by looking
|
# - This is an edge case that would be better handled by looking
|
||||||
# up the previous value of the entity from the recorder
|
# up the previous value of the entity from the recorder
|
||||||
if entity_description.never_resets and api_value == 0 and previous_value:
|
if never_resets and api_value == 0 and previous_value:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
(
|
(
|
||||||
"API value is 0, but this value should never reset, returning"
|
"API value is 0, but this value should never reset, returning"
|
||||||
@ -190,4 +193,4 @@ class SunWEGData:
|
|||||||
|
|
||||||
self.previous_values[variable] = return_value
|
self.previous_values[variable] = return_value
|
||||||
|
|
||||||
return return_value
|
return (return_value, native_unit_of_measurement)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
"""Read status of SunWEG inverters."""
|
"""Read status of SunWEG inverters."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
|
||||||
import logging
|
import logging
|
||||||
from types import MappingProxyType
|
from types import MappingProxyType
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@ -16,7 +15,6 @@ from homeassistant.const import CONF_NAME
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
|
||||||
|
|
||||||
from . import SunWEGData
|
from . import SunWEGData
|
||||||
from .const import CONF_PLANT_ID, DEFAULT_PLANT_ID, DOMAIN, DeviceType
|
from .const import CONF_PLANT_ID, DEFAULT_PLANT_ID, DOMAIN, DeviceType
|
||||||
@ -160,18 +158,20 @@ class SunWEGInverter(SensorEntity):
|
|||||||
name=name,
|
name=name,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(
|
|
||||||
self,
|
|
||||||
) -> StateType | datetime.datetime:
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
return self.probe.get_data(
|
|
||||||
self.entity_description,
|
|
||||||
device_type=self.device_type,
|
|
||||||
inverter_id=self.inverter_id,
|
|
||||||
deep_name=self.deep_name,
|
|
||||||
)
|
|
||||||
|
|
||||||
def update(self) -> None:
|
def update(self) -> None:
|
||||||
"""Get the latest data from the Sun WEG API and updates the state."""
|
"""Get the latest data from the Sun WEG API and updates the state."""
|
||||||
self.probe.update()
|
self.probe.update()
|
||||||
|
(
|
||||||
|
self._attr_native_value,
|
||||||
|
self._attr_native_unit_of_measurement,
|
||||||
|
) = self.probe.get_data(
|
||||||
|
api_variable_key=self.entity_description.api_variable_key,
|
||||||
|
api_variable_unit=self.entity_description.api_variable_unit,
|
||||||
|
deep_name=self.deep_name,
|
||||||
|
device_type=self.device_type,
|
||||||
|
inverter_id=self.inverter_id,
|
||||||
|
name=self.entity_description.name,
|
||||||
|
native_unit_of_measurement=self.native_unit_of_measurement,
|
||||||
|
never_resets=self.entity_description.never_resets,
|
||||||
|
previous_value_drop_threshold=self.entity_description.previous_value_drop_threshold,
|
||||||
|
)
|
||||||
|
@ -95,26 +95,41 @@ async def test_sunwegdata_get_data_drop_threshold() -> None:
|
|||||||
)
|
)
|
||||||
entity_description.previous_value_drop_threshold = 0.1
|
entity_description.previous_value_drop_threshold = 0.1
|
||||||
data.get_api_value.return_value = 3.0
|
data.get_api_value.return_value = 3.0
|
||||||
assert (
|
assert data.get_data(
|
||||||
data.get_data(
|
api_variable_key=entity_description.api_variable_key,
|
||||||
entity_description=entity_description, device_type=DeviceType.TOTAL
|
api_variable_unit=entity_description.api_variable_unit,
|
||||||
)
|
deep_name=None,
|
||||||
== 3.0
|
device_type=DeviceType.TOTAL,
|
||||||
)
|
inverter_id=0,
|
||||||
|
name=entity_description.name,
|
||||||
|
native_unit_of_measurement=entity_description.native_unit_of_measurement,
|
||||||
|
never_resets=entity_description.never_resets,
|
||||||
|
previous_value_drop_threshold=entity_description.previous_value_drop_threshold,
|
||||||
|
) == (3.0, None)
|
||||||
data.get_api_value.return_value = 2.91
|
data.get_api_value.return_value = 2.91
|
||||||
assert (
|
assert data.get_data(
|
||||||
data.get_data(
|
api_variable_key=entity_description.api_variable_key,
|
||||||
entity_description=entity_description, device_type=DeviceType.TOTAL
|
api_variable_unit=entity_description.api_variable_unit,
|
||||||
)
|
deep_name=None,
|
||||||
== 3.0
|
device_type=DeviceType.TOTAL,
|
||||||
)
|
inverter_id=0,
|
||||||
|
name=entity_description.name,
|
||||||
|
native_unit_of_measurement=entity_description.native_unit_of_measurement,
|
||||||
|
never_resets=entity_description.never_resets,
|
||||||
|
previous_value_drop_threshold=entity_description.previous_value_drop_threshold,
|
||||||
|
) == (3.0, None)
|
||||||
data.get_api_value.return_value = 2.8
|
data.get_api_value.return_value = 2.8
|
||||||
assert (
|
assert data.get_data(
|
||||||
data.get_data(
|
api_variable_key=entity_description.api_variable_key,
|
||||||
entity_description=entity_description, device_type=DeviceType.TOTAL
|
api_variable_unit=entity_description.api_variable_unit,
|
||||||
)
|
deep_name=None,
|
||||||
== 2.8
|
device_type=DeviceType.TOTAL,
|
||||||
)
|
inverter_id=0,
|
||||||
|
name=entity_description.name,
|
||||||
|
native_unit_of_measurement=entity_description.native_unit_of_measurement,
|
||||||
|
never_resets=entity_description.never_resets,
|
||||||
|
previous_value_drop_threshold=entity_description.previous_value_drop_threshold,
|
||||||
|
) == (2.8, None)
|
||||||
|
|
||||||
|
|
||||||
async def test_sunwegdata_get_data_never_reset() -> None:
|
async def test_sunwegdata_get_data_never_reset() -> None:
|
||||||
@ -127,23 +142,38 @@ async def test_sunwegdata_get_data_never_reset() -> None:
|
|||||||
)
|
)
|
||||||
entity_description.never_resets = True
|
entity_description.never_resets = True
|
||||||
data.get_api_value.return_value = 3.0
|
data.get_api_value.return_value = 3.0
|
||||||
assert (
|
assert data.get_data(
|
||||||
data.get_data(
|
api_variable_key=entity_description.api_variable_key,
|
||||||
entity_description=entity_description, device_type=DeviceType.TOTAL
|
api_variable_unit=entity_description.api_variable_unit,
|
||||||
)
|
deep_name=None,
|
||||||
== 3.0
|
device_type=DeviceType.TOTAL,
|
||||||
)
|
inverter_id=0,
|
||||||
|
name=entity_description.name,
|
||||||
|
native_unit_of_measurement=entity_description.native_unit_of_measurement,
|
||||||
|
never_resets=entity_description.never_resets,
|
||||||
|
previous_value_drop_threshold=entity_description.previous_value_drop_threshold,
|
||||||
|
) == (3.0, None)
|
||||||
data.get_api_value.return_value = 0
|
data.get_api_value.return_value = 0
|
||||||
assert (
|
assert data.get_data(
|
||||||
data.get_data(
|
api_variable_key=entity_description.api_variable_key,
|
||||||
entity_description=entity_description, device_type=DeviceType.TOTAL
|
api_variable_unit=entity_description.api_variable_unit,
|
||||||
)
|
deep_name=None,
|
||||||
== 3.0
|
device_type=DeviceType.TOTAL,
|
||||||
)
|
inverter_id=0,
|
||||||
|
name=entity_description.name,
|
||||||
|
native_unit_of_measurement=entity_description.native_unit_of_measurement,
|
||||||
|
never_resets=entity_description.never_resets,
|
||||||
|
previous_value_drop_threshold=entity_description.previous_value_drop_threshold,
|
||||||
|
) == (3.0, None)
|
||||||
data.get_api_value.return_value = 2.8
|
data.get_api_value.return_value = 2.8
|
||||||
assert (
|
assert data.get_data(
|
||||||
data.get_data(
|
api_variable_key=entity_description.api_variable_key,
|
||||||
entity_description=entity_description, device_type=DeviceType.TOTAL
|
api_variable_unit=entity_description.api_variable_unit,
|
||||||
)
|
deep_name=None,
|
||||||
== 2.8
|
device_type=DeviceType.TOTAL,
|
||||||
)
|
inverter_id=0,
|
||||||
|
name=entity_description.name,
|
||||||
|
native_unit_of_measurement=entity_description.native_unit_of_measurement,
|
||||||
|
never_resets=entity_description.never_resets,
|
||||||
|
previous_value_drop_threshold=entity_description.previous_value_drop_threshold,
|
||||||
|
) == (2.8, None)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user