From bb42eb11761176964ee1533256ac219896475f6d Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Wed, 25 Aug 2021 13:01:55 +0200 Subject: [PATCH] Warn if a sensor with state_class_total has a decreasing value (#55197) --- homeassistant/components/energy/sensor.py | 7 +++- homeassistant/components/sensor/recorder.py | 37 +++++++++++++++++++-- tests/components/sensor/test_recorder.py | 6 ++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/energy/sensor.py b/homeassistant/components/energy/sensor.py index 099ea8df0ab..45ef8ea5c17 100644 --- a/homeassistant/components/energy/sensor.py +++ b/homeassistant/components/energy/sensor.py @@ -298,7 +298,12 @@ class EnergyCostSensor(SensorEntity): ) return - if reset_detected(energy, float(self._last_energy_sensor_state)): + if reset_detected( + self.hass, + cast(str, self._config[self._adapter.entity_energy_key]), + energy, + float(self._last_energy_sensor_state), + ): # Energy meter was reset, reset cost sensor too self._reset(0) # Update with newly incurred cost diff --git a/homeassistant/components/sensor/recorder.py b/homeassistant/components/sensor/recorder.py index 77f91752327..2115cca2892 100644 --- a/homeassistant/components/sensor/recorder.py +++ b/homeassistant/components/sensor/recorder.py @@ -39,6 +39,7 @@ from homeassistant.const import ( VOLUME_CUBIC_METERS, ) from homeassistant.core import HomeAssistant, State +from homeassistant.helpers.entity import entity_sources import homeassistant.util.dt as dt_util import homeassistant.util.pressure as pressure_util import homeassistant.util.temperature as temperature_util @@ -106,6 +107,8 @@ UNIT_CONVERSIONS: dict[str, dict[str, Callable]] = { }, } +# Keep track of entities for which a warning about decreasing value has been logged +WARN_DIP = "sensor_warn_total_increasing_dip" # Keep track of entities for which a warning about unsupported unit has been logged WARN_UNSUPPORTED_UNIT = "sensor_warn_unsupported_unit" WARN_UNSTABLE_UNIT = "sensor_warn_unstable_unit" @@ -229,9 +232,36 @@ def _normalize_states( return DEVICE_CLASS_UNITS[device_class], fstates -def reset_detected(state: float, previous_state: float | None) -> bool: +def warn_dip(hass: HomeAssistant, entity_id: str) -> None: + """Log a warning once if a sensor with state_class_total has a decreasing value.""" + if WARN_DIP not in hass.data: + hass.data[WARN_DIP] = set() + if entity_id not in hass.data[WARN_DIP]: + hass.data[WARN_DIP].add(entity_id) + domain = entity_sources(hass).get(entity_id, {}).get("domain") + if domain in ["energy", "growatt_server", "solaredge"]: + return + _LOGGER.warning( + "Entity %s %shas state class total_increasing, but its state is " + "not strictly increasing. Please create a bug report at %s", + entity_id, + f"from integration {domain} " if domain else "", + "https://github.com/home-assistant/core/issues?q=is%3Aopen+is%3Aissue" + "+label%3A%22integration%3A+recorder%22", + ) + + +def reset_detected( + hass: HomeAssistant, entity_id: str, state: float, previous_state: float | None +) -> bool: """Test if a total_increasing sensor has been reset.""" - return previous_state is not None and state < 0.9 * previous_state + if previous_state is None: + return False + + if 0.9 * previous_state <= state < previous_state: + warn_dip(hass, entity_id) + + return state < 0.9 * previous_state def compile_statistics( @@ -337,7 +367,8 @@ def compile_statistics( fstate, ) elif state_class == STATE_CLASS_TOTAL_INCREASING and ( - old_state is None or reset_detected(fstate, new_state) + old_state is None + or reset_detected(hass, entity_id, fstate, new_state) ): reset = True _LOGGER.info( diff --git a/tests/components/sensor/test_recorder.py b/tests/components/sensor/test_recorder.py index 5b82fcf0506..0234a8c0613 100644 --- a/tests/components/sensor/test_recorder.py +++ b/tests/components/sensor/test_recorder.py @@ -427,6 +427,12 @@ def test_compile_hourly_sum_statistics_total_increasing_small_dip( ] } assert "Error while processing event StatisticsTask" not in caplog.text + assert ( + "Entity sensor.test1 has state class total_increasing, but its state is not " + "strictly increasing. Please create a bug report at https://github.com/" + "home-assistant/core/issues?q=is%3Aopen+is%3Aissue+label%3A%22integration%3A" + "+recorder%22" + ) in caplog.text def test_compile_hourly_energy_statistics_unsupported(hass_recorder, caplog):