141 lines
5.2 KiB
Markdown
141 lines
5.2 KiB
Markdown
|
|
# 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 ~3–5s, 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.
|