Summary
sensor_collector.py's runtime (live) collection path diffs two live HA-poll snapshots to compute per-period energy deltas (battery_discharged, grid_imported, home_consumption, etc.), rather than pinning to the exact period boundary the way the historical/backfill path already does (influxdb_helper.py: "last InfluxDB value ≤ period_end").
Because the underlying HA counters (e.g. Growatt cumulative discharge energy) update on their own cadence, a counter tick that physically belongs to one period can land on the wrong side of a live-poll window and get attributed to the following period instead — producing a "0 → double" pattern.
Evidence
Found while investigating #381 / PR #385. Full-night analysis of a debug bundle (bess-debug-2026-07-22-065145.md, gist linked in #381) showed this pattern 3 times in one night (periods 5→6, 9→10, 25→26): a period reporting battery_discharged=0.000 immediately followed by a period reporting roughly double the SOE-implied value for that pair. Aggregate reconciliation across the full 27-period night (SOE-implied 2.708 kWh vs. reported 2.800 kWh, ~3.4%) is consistent with this being a real, if intermittent, attribution artifact.
Full analysis: #385 (comment)
This is flagged as an unproven hypothesis in that comment — 5 of 8 zero-discharge periods in the same window did NOT show a doubled follow-up, so this needs verification, not just a fix, before being called confirmed.
Relevant code
core/bess/sensor_collector.py:189-227 (runtime vs. historical branch), :603-654 (_get_period_readings_from_live_sensors)
core/bess/influxdb_helper.py:662-693 (the boundary-pinning logic already used for historical/backfill)
Suggested fix direction
Pin runtime-mode period boundaries the same way the historical path does (query InfluxDB for the last value at/before the period boundary) instead of diffing two arbitrary live-poll instants. Needs verification against real data (ideally a fresh debug capture) that this measurably removes the "0 → double" pattern before considering it resolved.
Related
Summary
sensor_collector.py's runtime (live) collection path diffs two live HA-poll snapshots to compute per-period energy deltas (battery_discharged,grid_imported,home_consumption, etc.), rather than pinning to the exact period boundary the way the historical/backfill path already does (influxdb_helper.py: "last InfluxDB value ≤ period_end").Because the underlying HA counters (e.g. Growatt cumulative discharge energy) update on their own cadence, a counter tick that physically belongs to one period can land on the wrong side of a live-poll window and get attributed to the following period instead — producing a "0 → double" pattern.
Evidence
Found while investigating #381 / PR #385. Full-night analysis of a debug bundle (
bess-debug-2026-07-22-065145.md, gist linked in #381) showed this pattern 3 times in one night (periods 5→6, 9→10, 25→26): a period reportingbattery_discharged=0.000immediately followed by a period reporting roughly double the SOE-implied value for that pair. Aggregate reconciliation across the full 27-period night (SOE-implied 2.708 kWh vs. reported 2.800 kWh, ~3.4%) is consistent with this being a real, if intermittent, attribution artifact.Full analysis: #385 (comment)
This is flagged as an unproven hypothesis in that comment — 5 of 8 zero-discharge periods in the same window did NOT show a doubled follow-up, so this needs verification, not just a fix, before being called confirmed.
Relevant code
core/bess/sensor_collector.py:189-227(runtime vs. historical branch),:603-654(_get_period_readings_from_live_sensors)core/bess/influxdb_helper.py:662-693(the boundary-pinning logic already used for historical/backfill)Suggested fix direction
Pin runtime-mode period boundaries the same way the historical path does (query InfluxDB for the last value at/before the period boundary) instead of diffing two arbitrary live-poll instants. Needs verification against real data (ideally a fresh debug capture) that this measurably removes the "0 → double" pattern before considering it resolved.
Related