fix 5min spikes

This commit is contained in:
2026-05-01 19:10:21 -04:00
parent e1b180e230
commit a1acf479f0
3 changed files with 150 additions and 0 deletions

140
LVX6048/2026-05-01.md Normal file
View File

@@ -0,0 +1,140 @@
# 2026-05-01 — fix 5-minute spikes on AC-output power time-series
## Symptom
On both inverters' apparent-power and active-power Influx series, a tall
rectangular spike to **exactly 6000 VA / 6000 W** appeared every ~5 minutes.
The spike was simultaneous on both units even though they are not paralleled
on AC output (and on this rig the AC outputs aren't even tied to a common
load), which ruled out any real-load mechanism.
90-min sample (idle unit 2, baseline ~47 VA / ~0 W):
| metric | spike value | spike count | inter-spike gap |
|-----------------------|---------------|-------------|-----------------|
| `VA` | **6000** (only) | 36 / 30 min | pairs ~35s, 298s between pairs |
| `W` | **6000** (only) | 12 / 30 min | same pattern |
Unit 1 spiked at `:37:12 / :42:15 / :47:17 / …`, unit 2 at `:37:44 / :42:46 / …`.
Each cycle is exactly 5 min; the two daemons sit ~32 s out of phase, so on
charts binned > 1 min they look simultaneous.
## Root cause
`6000` is the LVX6048's **nameplate** apparent / active power. Two PI18
commands return that field:
- `GS` (every 5 s): live measurement
- `PIRI` (every 300 s): nameplate / configured rating
In `powermon-patches/pi18.py` both fields share the same `description`
string (`"AC Output Apparent Power"`, `"AC Output Active Power"`).
Powermon's `outputformats/hass.py` slugifies `description` into the HA
entity_id with **no per-command namespace**, so both publish to:
```
homeassistant/sensor/lvx6048_X_ac_output_apparent_power/state
homeassistant/sensor/lvx6048_X_ac_output_active_power/state
```
Every 300 s when PIRI fires, the entity is written with `6000` for one
publish; the next GS (≤5 s later) restores the live value. HA's recorder
captures both → Influx records a 6000-valued sample tagged to the live
entity. Hence the periodic rectangular spike.
The same collision exists for several other PIRI fields whose descriptions
duplicate live GS fields:
- `AC Input Voltage`
- `AC Input Current` *(not in GS, but shadows the live current series via
PIRI's nameplate input rating)*
- `AC Output Voltage`
- `AC Output Frequency`
- `AC Output Current`
- `Battery Voltage`
Same artifact, just less visible because nameplate values for those are
close to live values during steady-state operation.
## Fix
Add `excl_filter` to the `PIRI` command block in both powermon configs
(matches the existing pattern used on `GS` for dead/dummy fields). PIRI's
job in this stack is to publish *configured* thresholds — bulk/float
voltages, charging-current ceilings, source priorities, etc. The fields
that duplicate GS measurements provide no value and only corrupt the
recorder series.
```yaml
- command: PIRI
trigger:
every: 300
outputs:
- type: mqtt
topic: powermon/lvx6048_X/PIRI
format:
type: hass
discovery_prefix: homeassistant
entity_id_prefix: lvx6048_X
excl_filter: '^(ac_input_voltage|ac_input_current|ac_output_voltage|ac_output_frequency|ac_output_current|ac_output_apparent_power|ac_output_active_power|battery_voltage)$'
```
Applied to both `config/powermon/powermon.yaml` and `…/powermon2.yaml`,
and mirrored to the live `~/.config/powermon/` deploys.
## Net effect
| Metric | Before | After |
|-----------------------------------------|----------|-------|
| `VA` series spurious 6000 spikes / 5 min| 2/inverter| 0 |
| `W` series spurious 6000 spikes / 5 min| 2/inverter| 0 |
| PIRI fields published per inverter | 26 | 18 |
| PIRI fields kept (battery/charge/priority configs) | — | all retained |
PIRI configuration entities (battery thresholds, MCHGC ceilings, output
priority, etc.) are unchanged — they continue to update every 300 s on
their own entity_ids.
## Files touched
```
M LVX6048/config/powermon/powermon.yaml (excl_filter on PIRI)
M LVX6048/config/powermon/powermon2.yaml (same)
A LVX6048/2026-05-01.md (this file)
```
## How to verify
```bash
sudo systemctl restart powermon.service powermon2.service
# Watch one PIRI cycle (≤5 min) — apparent power should NOT publish a 6000:
mosquitto_sub -h 10.0.0.41 -u mqtt -P <pass> \
-t 'homeassistant/sensor/lvx6048_+_ac_output_apparent_power/state' -W 360
# Or query Influx after one full cycle:
influx -host 10.0.0.41 -username homeassistant -password <pass> \
-database homeassistant -execute "
SELECT count(\"value\") FROM \"VA\"
WHERE (\"entity_id\" = 'lvx6048_lvx6048_1_ac_output_apparent_power'
OR \"entity_id\" = 'lvx6048_lvx6048_2_ac_output_apparent_power')
AND \"value\" = 6000
AND time > now() - 30m"
# Expect: count → 0 once the next two PIRI cycles have passed without spikes.
```
## Rollback
```bash
git -C ~/solar checkout HEAD~1 -- LVX6048/config/powermon/
cp ~/solar/LVX6048/config/powermon/powermon{,2}.yaml ~/.config/powermon/
# (re-edit ~/.config/powermon/*.yaml to restore real MQTT_PASSWORD)
sudo systemctl restart powermon.service powermon2.service
```
## Upstream-fix candidate
Cleaner (but invasive) alternative would patch `outputformats/hass.py` to
namespace entity_ids by command (e.g., `_settings_` infix for PIRI). Not
worth the patch maintenance — the `excl_filter` is one line per command
and survives powermon upgrades.

View File

@@ -55,6 +55,11 @@ commands:
type: hass
discovery_prefix: homeassistant
entity_id_prefix: lvx6048_1
# Drop fields whose description (and therefore entity_id slug) shadows
# GS's live measurements. PIRI's values for these are nameplate /
# configured-rating, not live, so they overwrite the live series every
# 300s producing 6000 VA / 6000 W spikes (LVX6048 nameplate).
excl_filter: '^(ac_input_voltage|ac_input_current|ac_output_voltage|ac_output_frequency|ac_output_current|ac_output_apparent_power|ac_output_active_power|battery_voltage)$'
- command: ET
trigger:

View File

@@ -52,6 +52,11 @@ commands:
type: hass
discovery_prefix: homeassistant
entity_id_prefix: lvx6048_2
# Drop fields whose description (and therefore entity_id slug) shadows
# GS's live measurements. PIRI's values for these are nameplate /
# configured-rating, not live, so they overwrite the live series every
# 300s producing 6000 VA / 6000 W spikes (LVX6048 nameplate).
excl_filter: '^(ac_input_voltage|ac_input_current|ac_output_voltage|ac_output_frequency|ac_output_current|ac_output_apparent_power|ac_output_active_power|battery_voltage)$'
- command: ET
trigger: