Skip to content

Commit 78fd1c2

Browse files
committed
Make RestoreSensor more resilience
1 parent d06186d commit 78fd1c2

2 files changed

Lines changed: 24 additions & 19 deletions

File tree

custom_components/victron_mqtt/sensor.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ def _normalize_value(value: Any) -> Any:
131131
async def async_added_to_hass(self) -> None:
132132
"""Restore persistent state for FormulaMetric energy sensors."""
133133

134-
# Only restore for:
135-
# 1. Total increasing sensors (like cumulative energy)
136-
# 2. FormulaMetrics (calculated values)
134+
# Only restore for cumulative FormulaMetric sensors (TOTAL / TOTAL_INCREASING).
135+
# These metrics start from 0 on each HA restart, so we restore the
136+
# previous accumulated value as a baseline and add new increments on top.
137137
should_restore = self.state_class in [
138138
SensorStateClass.TOTAL_INCREASING,
139139
SensorStateClass.TOTAL,
@@ -145,23 +145,29 @@ async def async_added_to_hass(self) -> None:
145145
return
146146

147147
last_state = await self.async_get_last_state()
148-
if last_state is None or last_state.state in (None, "unknown"):
148+
if last_state is None or last_state.state in (None, "unknown", "unavailable"):
149149
await super().async_added_to_hass()
150150
_LOGGER.info(
151-
"Baseline is missing. Probably first load for %s", self.entity_id
152-
)
151+
"Baseline is missing. Probably first load for %s", self.entity_id
152+
)
153+
return
154+
155+
if not isinstance(self._attr_native_value, int | float):
156+
_LOGGER.warning(
157+
"Cannot restore baseline for %s: current value is %r (expected numeric)",
158+
self.entity_id,
159+
self._attr_native_value,
160+
)
161+
await super().async_added_to_hass()
153162
return
154163

155-
assert isinstance(self._attr_native_value, (int, float)), (
156-
"sensor with stored baseline value must be numeric"
157-
)
158164
try:
159165
self._baseline = float(last_state.state)
160166
self._attr_native_value += self._baseline
161167
_LOGGER.info(
162168
"Restored baseline of %.3f for %s", self._baseline, self.entity_id
163169
)
164-
except ValueError:
170+
except (ValueError, TypeError):
165171
_LOGGER.warning(
166172
"Could not restore state for %s: invalid value '%s' (type: %s)",
167173
self.entity_id,

tests/test_hub.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -536,11 +536,11 @@ async def test_sensor_with_baseline(
536536
snapshot: SnapshotAssertion,
537537
init_integration,
538538
) -> None:
539-
"""Test that baseline is NOT restored for TOTAL state_class (only TOTAL_INCREASING).
540-
541-
The current implementation only restores baseline for sensors with
542-
SensorStateClass.TOTAL_INCREASING. FormulaMetric sensors with CUMULATIVE
543-
nature get mapped to SensorStateClass.TOTAL, so baseline is not restored.
539+
"""Test that baseline IS restored for FormulaMetric sensors with TOTAL state_class.
540+
541+
FormulaMetric energy sensors start from 0 on each HA restart. The baseline
542+
mechanism restores the previous accumulated value so the sensor continues
543+
from where it left off, preventing spikes in the Energy Dashboard.
544544
"""
545545
victron_hub, mock_config_entry = init_integration
546546
# Mock time.monotonic() to return a fixed time
@@ -573,12 +573,11 @@ async def test_sensor_with_baseline(
573573
energy_entities = [e for e in entities if "energy" in e.entity_id]
574574
assert len(energy_entities) > 0
575575

576-
# Since state_class is TOTAL (not TOTAL_INCREASING), baseline is NOT restored
577-
# The value should be 0.0 (the FormulaMetric's initial value)
576+
# Since state_class is TOTAL and this is a FormulaMetric, baseline IS restored
577+
# The value = baseline (1000.0) + formula accumulated energy (0.004)
578578
state = hass.states.get(energy_entities[0].entity_id)
579579
assert state is not None
580-
# Value should be the metric's initial value, NOT the baseline
581-
assert float(state.state) == 1000.004 # Not 0.004
580+
assert float(state.state) == 1000.004
582581
# Should have created two entity
583582
assert len(entities) == 2
584583
assert entities == snapshot

0 commit comments

Comments
 (0)