Teach long term statistics that unit 'rpm' is same as 'RPM' (#80012)

* Teach long term statistics that unit 'rpm' is same as 'RPM'

* Add tests
This commit is contained in:
Erik Montnemery 2022-10-11 10:32:01 +02:00 committed by GitHub
parent edad6d0f26
commit 69d935b7bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 217 additions and 4 deletions

View file

@ -23,7 +23,7 @@ from homeassistant.components.recorder.models import (
StatisticMetaData,
StatisticResult,
)
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT, REVOLUTIONS_PER_MINUTE
from homeassistant.core import HomeAssistant, State, split_entity_id
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity import entity_sources
@ -47,6 +47,10 @@ DEFAULT_STATISTICS = {
STATE_CLASS_TOTAL_INCREASING: {"sum"},
}
EQUIVALENT_UNITS = {
"RPM": REVOLUTIONS_PER_MINUTE,
}
# Keep track of entities for which a warning about decreasing value has been logged
SEEN_DIP = "sensor_seen_total_increasing_dip"
WARN_DIP = "sensor_warn_total_increasing_dip"
@ -113,10 +117,20 @@ def _time_weighted_average(
def _get_units(fstates: list[tuple[float, State]]) -> set[str | None]:
"""Return True if all states have the same unit."""
"""Return a set of all units."""
return {item[1].attributes.get(ATTR_UNIT_OF_MEASUREMENT) for item in fstates}
def _equivalent_units(units: set[str | None]) -> bool:
"""Return True if the units are equivalent."""
if len(units) == 1:
return True
units = {
EQUIVALENT_UNITS[unit] if unit in EQUIVALENT_UNITS else unit for unit in units
}
return len(units) == 1
def _parse_float(state: str) -> float:
"""Parse a float string, throw on inf or nan."""
fstate = float(state)
@ -165,7 +179,7 @@ def _normalize_states(
# The unit used by this sensor doesn't support unit conversion
all_units = _get_units(fstates)
if len(all_units) > 1:
if not _equivalent_units(all_units):
if WARN_UNSTABLE_UNIT not in hass.data:
hass.data[WARN_UNSTABLE_UNIT] = set()
if entity_id not in hass.data[WARN_UNSTABLE_UNIT]:
@ -442,7 +456,9 @@ def _compile_statistics( # noqa: C901
) in to_process:
# Check metadata
if old_metadata := old_metadatas.get(entity_id):
if old_metadata[1]["unit_of_measurement"] != statistics_unit:
if not _equivalent_units(
{old_metadata[1]["unit_of_measurement"], statistics_unit}
):
if WARN_UNSTABLE_UNIT not in hass.data:
hass.data[WARN_UNSTABLE_UNIT] = set()
if entity_id not in hass.data[WARN_UNSTABLE_UNIT]: