Tessie: log warning instead of raising UpdateFailed for missing energy history (#168068)

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
fender4645
2026-04-23 22:47:15 +02:00
committed by GitHub
co-authored by Claude Sonnet 4.6 Copilot
parent b4c8452a5a
commit e5cd1e2830
3 changed files with 52 additions and 13 deletions
@@ -224,10 +224,11 @@ class TessieEnergyHistoryCoordinator(DataUpdateCoordinator[dict[str, Any]]):
or not isinstance(data.get("time_series"), list)
or not data["time_series"]
):
raise UpdateFailed(
translation_domain=DOMAIN,
translation_key="invalid_energy_history_data",
_LOGGER.warning(
"Tessie returned no energy history time_series for coordinator %s; skipping update",
self.config_entry.entry_id,
)
return self.data
time_series = data["time_series"]
output: dict[str, Any] = {}
+1 -1
View File
@@ -638,4 +638,4 @@ class TessieEnergyHistorySensorEntity(TessieEnergyHistoryEntity, SensorEntity):
"""Update the attributes of the sensor."""
self._attr_available = self._value is not None
self._attr_native_value = self._value
self._attr_last_reset = self.coordinator.data["_period_start"]
self._attr_last_reset = self.coordinator.data.get("_period_start")
+47 -9
View File
@@ -1,5 +1,6 @@
"""Test the Tessie sensor platform."""
from copy import deepcopy
from datetime import timedelta
from freezegun.api import FrozenDateTimeFactory
@@ -14,11 +15,17 @@ from homeassistant.components.tessie.coordinator import (
TESSIE_SYNC_INTERVAL,
)
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import STATE_ON, STATE_UNAVAILABLE, Platform
from homeassistant.const import STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import UpdateFailed
from .common import ERROR_AUTH, ERROR_CONNECTION, ERROR_UNKNOWN, setup_platform
from .common import (
ENERGY_HISTORY,
ERROR_AUTH,
ERROR_CONNECTION,
ERROR_UNKNOWN,
setup_platform,
)
from tests.common import async_fire_time_changed
@@ -184,21 +191,52 @@ async def test_coordinator_energy_history_error(
async def test_coordinator_energy_history_invalid_data(
hass: HomeAssistant, mock_energy_history, freezer: FrozenDateTimeFactory
) -> None:
"""Tests that the energy history coordinator handles invalid data."""
"""Tests that the energy history coordinator handles invalid data gracefully."""
entry = await setup_platform(hass, [Platform.SENSOR])
coordinator = entry.runtime_data.energysites[0].history_coordinator
assert coordinator is not None
# Capture state after successful initial load
state_before = hass.states.get("sensor.energy_site_grid_imported").state
mock_energy_history.reset_mock()
mock_energy_history.side_effect = lambda *a, **kw: {"response": {}}
freezer.tick(TESSIE_ENERGY_HISTORY_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
mock_energy_history.assert_called_once()
assert (
hass.states.get("sensor.energy_site_grid_imported").state == STATE_UNAVAILABLE
)
assert isinstance(coordinator.last_exception, UpdateFailed)
assert coordinator.last_exception.translation_domain == DOMAIN
assert coordinator.last_exception.translation_key == "invalid_energy_history_data"
# Sensor should retain last good state rather than becoming unavailable
assert hass.states.get("sensor.energy_site_grid_imported").state == state_before
assert coordinator.last_exception is None
async def test_coordinator_energy_history_cold_start_invalid_data(
hass: HomeAssistant, mock_energy_history, freezer: FrozenDateTimeFactory
) -> None:
"""Tests cold-start fallback when the very first energy history fetch has invalid data."""
mock_energy_history.side_effect = lambda *a, **kw: {"response": {}}
entry = await setup_platform(hass, [Platform.SENSOR])
coordinator = entry.runtime_data.energysites[0].history_coordinator
assert coordinator is not None
# Coordinator should not have raised an exception; data stays empty
assert coordinator.last_exception is None
assert coordinator.data == {}
# Sensor should be unknown until the first successful fetch
assert hass.states.get("sensor.energy_site_grid_imported").state == STATE_UNKNOWN
# Now recover: restore valid energy history data and trigger an update
mock_energy_history.side_effect = lambda *a, **kw: deepcopy(ENERGY_HISTORY)
mock_energy_history.reset_mock()
freezer.tick(TESSIE_ENERGY_HISTORY_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
mock_energy_history.assert_called_once()
# Coordinator should have real data and no exception
assert coordinator.last_exception is None
assert coordinator.data["solar_energy_exported"] == 724