Filter implausible inverter readings via configurable peak AC power#358
Open
Filter implausible inverter readings via configurable peak AC power#358
Conversation
Some inverters report garbage values (MW or TWh range) at dawn and dusk when irradiance is too low for a stable reading. Add an optional peak AC power option to the config entry's options flow that filters those out: * Power-like sensors (W, VA, VAr) above the configured peak are dropped and replaced with None. * Energy sensors are checked against a delta limit derived from the peak power times the scan interval (x 2 safety factor); on a violation the last known value is returned, keeping total_increasing stats intact. * The first energy read after a restart with no restored baseline is discarded so a potential garbage value never becomes the baseline. * Bug fix: async_added_to_hass now also seeds lastKnown from the restored state so the existing val == 0 fallback and the new delta filter both work on the very first poll after a restart. Leaving the option empty disables the filter completely - no behavior change for existing installations. Tests added for the power filter.
hilman2
added a commit
to hilman2/ha-sunspec2
that referenced
this pull request
Apr 7, 2026
Some SunSpec inverters report garbage values (MW or TWh range) at
dawn and dusk when irradiance is too low for a stable reading. These
spikes poison long-term Recorder statistics and the user has to clean
them up by hand from the database.
This adds an opt-in plausibility filter at the integration level so
users do not need workarounds in templates / utility_meter /
sensor.statistics.
- New options-flow field "Peak AC power of the inverter (kW,
optional)" in the existing model_options step. Empty disables
the filter, no behaviour change for existing installations.
- Power-like sensors (W / VA / VAr) above the configured peak are
dropped (native_value returns None) and a warning is logged.
- Energy sensors are checked against a delta limit derived from
peak_kw * scan_interval * 2 (safety factor in
ENERGY_DELTA_SAFETY_FACTOR). On a violation the last known value
is returned, keeping total_increasing stats intact - reusing the
same mechanism as the existing val == 0 fallback.
- The very first energy read after a restart with no restored
baseline is discarded so a potential garbage value never becomes
the baseline. The next poll has a real baseline.
- Bug fix in SunSpecEnergySensor.async_added_to_hass: the restored
state was written to the unused last_known_value attribute but
never to lastKnown - now both are populated, so the existing
val == 0 fallback and the new delta filter both work on the very
first poll after a restart, not only after the second one.
The optional float field uses suggested_value instead of default so
the form input can stay genuinely empty (an empty value disables the
filter rather than coercing to 0).
Plus full English + German translations for the model_options step.
Previously the form fields rendered as their raw config keys; now
each one has a human label and the description explains the peak AC
power semantics.
Ported from hilman2's PR CJNE/ha-sunspec#358 against the upstream
integration. Adapted to our typed-error context, our self._log
adapter, and our existing CONF_CAPTURE_RAW field which was already
in the model_options step.
Tests: two new in tests/test_sensor.py:
test_sensor_power_filtered_by_peak_limit
Configures a peak of 0.5 kW; the mock 800 W reading is dropped
and the entity ends up unknown / unavailable.
test_sensor_power_passes_through_when_below_limit
Configures a peak of 10 kW; the mock 800 W reading passes through
unchanged.
94/94 passed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Some SunSpec inverters report garbage values (MW or TWh range) at dawn
and dusk when irradiance is too low for a stable reading. These spikes
poison long-term statistics in Home Assistant and require manual cleanup.
This adds an opt-in plausibility filter at the integration level so users
don't need workarounds in templates / utility_meter / sensor.statistics.
What's in the PR
in the existing model_options step. Empty disables the filter — no
behavior change for existing installations.
W,VA,VAr) above the configured peak aredropped (replaced with
None) and a warning is logged.peak_kw × scan_interval × 2(safety factor). On a violation the lastknown value is returned, keeping
total_increasingstats intact —reusing the same mechanism as the existing
val == 0fallback.is discarded so a potential garbage value never becomes the baseline.
SunSpecEnergySensor.async_added_to_hass: the restoredstate was written to the unused
last_known_valueattribute but neverto
lastKnown— now both are populated, so the existingval == 0fallback and the new delta filter both work on the very first poll
after a restart.
Testing
pytest tests/ --no-cov→ 33 passed locally (HA 2026.2.3, Python 3.13).tests/test_sensor.pycover the power filter(filtered above limit, passes through below limit).
black+flake8clean.Notes for the maintainer
options flow.
separate option if you'd prefer.