diff --git a/homeassistant/components/energy/sensor.py b/homeassistant/components/energy/sensor.py index 0c4c5eeb3b9..462c3f3215d 100644 --- a/homeassistant/components/energy/sensor.py +++ b/homeassistant/components/energy/sensor.py @@ -330,6 +330,7 @@ class EnergyCostSensor(SensorEntity): cast(str, self._config[self._adapter.entity_energy_key]), energy, float(self._last_energy_sensor_state.state), + self._last_energy_sensor_state, ): # Energy meter was reset, reset cost sensor too energy_state_copy = copy.copy(energy_state) diff --git a/homeassistant/components/sensor/recorder.py b/homeassistant/components/sensor/recorder.py index 00f5ed4453f..3ac4cf4e53b 100644 --- a/homeassistant/components/sensor/recorder.py +++ b/homeassistant/components/sensor/recorder.py @@ -287,7 +287,7 @@ def _suggest_report_issue(hass: HomeAssistant, entity_id: str) -> str: return report_issue -def warn_dip(hass: HomeAssistant, entity_id: str) -> None: +def warn_dip(hass: HomeAssistant, entity_id: str, state: State) -> None: """Log a warning once if a sensor with state_class_total has a decreasing value. The log will be suppressed until two dips have been seen to prevent warning due to @@ -308,14 +308,17 @@ def warn_dip(hass: HomeAssistant, entity_id: str) -> None: return _LOGGER.warning( "Entity %s %shas state class total_increasing, but its state is " - "not strictly increasing. Please %s", + "not strictly increasing. Triggered by state %s with last_updated set to %s. " + "Please %s", entity_id, f"from integration {domain} " if domain else "", + state.state, + state.last_updated.isoformat(), _suggest_report_issue(hass, entity_id), ) -def warn_negative(hass: HomeAssistant, entity_id: str) -> None: +def warn_negative(hass: HomeAssistant, entity_id: str, state: State) -> None: """Log a warning once if a sensor with state_class_total has a negative value.""" if WARN_NEGATIVE not in hass.data: hass.data[WARN_NEGATIVE] = set() @@ -324,28 +327,34 @@ def warn_negative(hass: HomeAssistant, entity_id: str) -> None: domain = entity_sources(hass).get(entity_id, {}).get("domain") _LOGGER.warning( "Entity %s %shas state class total_increasing, but its state is " - "negative. Please %s", + "negative. Triggered by state %s with last_updated set to %s. Please %s", entity_id, f"from integration {domain} " if domain else "", + state.state, + state.last_updated.isoformat(), _suggest_report_issue(hass, entity_id), ) def reset_detected( - hass: HomeAssistant, entity_id: str, state: float, previous_state: float | None + hass: HomeAssistant, + entity_id: str, + fstate: float, + previous_fstate: float | None, + state: State, ) -> bool: """Test if a total_increasing sensor has been reset.""" - if previous_state is None: + if previous_fstate is None: return False - if 0.9 * previous_state <= state < previous_state: - warn_dip(hass, entity_id) + if 0.9 * previous_fstate <= fstate < previous_fstate: + warn_dip(hass, entity_id, state) - if state < 0: - warn_negative(hass, entity_id) + if fstate < 0: + warn_negative(hass, entity_id, state) raise HomeAssistantError - return state < 0.9 * previous_state + return fstate < 0.9 * previous_fstate def _wanted_statistics(sensor_states: list[State]) -> dict[str, set[str]]: @@ -547,13 +556,15 @@ def _compile_statistics( # noqa: C901 elif state_class == STATE_CLASS_TOTAL_INCREASING: try: if old_state is None or reset_detected( - hass, entity_id, fstate, new_state + hass, entity_id, fstate, new_state, state ): reset = True _LOGGER.info( - "Detected new cycle for %s, value dropped from %s to %s", + "Detected new cycle for %s, value dropped from %s to %s, " + "triggered by state with last_updated set to %s", entity_id, new_state, + state.last_updated.isoformat(), fstate, ) except HomeAssistantError: diff --git a/tests/components/sensor/test_recorder.py b/tests/components/sensor/test_recorder.py index 96335d435da..032ff85561c 100644 --- a/tests/components/sensor/test_recorder.py +++ b/tests/components/sensor/test_recorder.py @@ -707,8 +707,10 @@ def test_compile_hourly_sum_statistics_negative_state( seq = [15, 16, 15, 16, 20, -20, 20, 10] states = {entity_id: []} + offending_state = 5 if state := hass.states.get(entity_id): states[entity_id].append(state) + offending_state = 6 one = zero for i in range(len(seq)): one = one + timedelta(seconds=5) @@ -745,8 +747,11 @@ def test_compile_hourly_sum_statistics_negative_state( }, ] assert "Error while processing event StatisticsTask" not in caplog.text + state = states[entity_id][offending_state].state + last_updated = states[entity_id][offending_state].last_updated.isoformat() assert ( - f"Entity {entity_id} {warning_1}has state class total_increasing, but its state is negative" + f"Entity {entity_id} {warning_1}has state class total_increasing, but its state " + f"is negative. Triggered by state {state} with last_updated set to {last_updated}." in caplog.text ) assert warning_2 in caplog.text @@ -965,15 +970,17 @@ def test_compile_hourly_sum_statistics_total_increasing_small_dip( wait_recording_done(hass) 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" + "strictly increasing." ) not in caplog.text recorder.do_adhoc_statistics(start=period2) wait_recording_done(hass) + state = states["sensor.test1"][6].state + last_updated = states["sensor.test1"][6].last_updated.isoformat() 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" + f"strictly increasing. Triggered by state {state} with last_updated set to " + f"{last_updated}. Please create a bug report at https://github.com/home-assistant" + "/core/issues?q=is%3Aopen+is%3Aissue" ) in caplog.text statistic_ids = list_statistic_ids(hass) assert statistic_ids == [