Fix/feedthrough Kirchhoff derivation#138
Merged
cayossarian merged 6 commits intomainfrom Apr 20, 2026
Merged
Conversation
The panel's native energy.ebus.device.lugs.downstream active-power
carries a systematic ~400-550 W offset and its imported-energy counter
can emit non-monotonic (including negative) cumulative values, making
both readings unusable for either instantaneous power or lifetime
energy accounting.
Main meter and per-branch readings remain accurate, so apply the
energy-balance identity at the main bus:
P_main = P_feedthrough + Σ(branches, load-perspective)
=> P_feedthrough = P_main − Σ(branches)
Feedthrough power/energy are now derived at snapshot build time in
HomieDeviceConsumer._build_snapshot and mirrored in the dirty-circuit
rebuild path. The synthesized PV virtual circuit carries the correct
load-perspective sign so it participates safely; unmapped tab entries
contribute zero. Per-phase currents (l1/l2) continue to be read from
the downstream-lugs node — those readings are orthogonal to the
active-power / energy-counter defects.
No public interface change: field names and types are unchanged;
only the values' source shifts.
Version bumped to 2.6.3.
scripts/validate_lug_derivation/ compares the panel's native downstream-lugs readings against the v1 REST API readings against a Kirchhoff-derived value (main − Σcircuits), using both span-panel-api==1.1.15 (for v1 REST) and the current workspace library (for v2 MQTT) in parallel ephemeral environments driven by uv run. Used to diagnose the feedthrough power/energy defect on MQTT v2 and to confirm that the Kirchhoff derivation produces physically- consistent results across both APIs. See v1-only "Unmapped Tab" circuits vs v2-only "Commissioned PV System" virtual circuit: both represent the same physical PV in opposite sign conventions, which the partitioning logic in compare.py accounts for. A gitignore rule for scripts/validate_lug_derivation/run_local.sh keeps a credentialed driver script out of git — users copy and edit that template with their own host / v1 token / v2 passphrase.
c0aede3 to
be0b49a
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the MQTT/Homie (v2) snapshot construction to compute “feedthrough” from an energy-balance/Kirchhoff-style derivation (main meter minus sum of circuit snapshots), and bumps the package version with supporting tests and validation scripts.
Changes:
- Derive feedthrough power/energy from upstream-lugs (main) minus Σ(circuits) in
HomieDeviceConsumer, including the dirty-circuit rebuild path. - Update MQTT/Homie tests to validate the new derivation behavior and ensure downstream-lugs power/energy are ignored.
- Add validation scripts to capture/compare v1 vs v2 snapshots and bump version/changelog entries.
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
src/span_panel_api/mqtt/homie.py |
Adds _derive_feedthrough() and applies it in full and partial snapshot rebuild paths; stops reading downstream-lugs power/energy. |
tests/test_mqtt_homie.py |
Replaces downstream-lugs→feedthrough assertions with derivation-based expectations; adjusts generic-lugs test to validate downstream current fields. |
scripts/validate_lug_derivation/v1_reader.py |
New helper to capture v1 REST snapshots for comparison. |
scripts/validate_lug_derivation/v2_reader.py |
New helper to capture v2 MQTT snapshots from the current workspace install. |
scripts/validate_lug_derivation/compare.py |
New script to run both readers and print side-by-side comparisons (including derived feedthrough). |
pyproject.toml |
Bumps project version to 2.6.3. |
uv.lock |
Updates locked version metadata for editable span-panel-api to 2.6.3. |
CHANGELOG.md |
Adds 2.6.3 entry documenting the feedthrough derivation change. |
.gitignore |
Ignores a local credentialed runner script for the validation workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Per-direction energy derivation (main.consumed - Σcircuit.consumed,
and likewise for produced) is mathematically unsound when branches
flow bidirectionally. The classic case is PV self-consumption on the
main panel: Σ(branch.consumed) can exceed main.consumed even when the
net balance is valid, so the naive subtraction emits negative
cumulative feedthrough counters.
_derive_feedthrough now derives the net-energy identity
feedthrough_net = (main.consumed - main.produced) - Σ(branch.net)
and splits it into non-negative consumed / produced components. Added
a PV-self-consumption regression test.
Also clarified field_metadata.py: the downstream-lugs entries for
feedthrough power/energy are retained only to inherit unit/datatype
from the Homie schema; the runtime values are derived.
Addresses PR #138 review feedback.
… fix The library now derives feedthrough via Kirchhoff, so downstream consumers no longer see the firmware defect. But the SPAN API is in beta and carries no version signal — we need to detect empirically when SPAN ships the fix upstream (tracked at spanio/SPAN-API-Client-Docs#13). v2_reader.py now reaches into the MQTT accumulator to capture the raw downstream-lugs active-power / imported-energy / exported-energy values alongside the library's derived snapshot (same-repo diagnostic access via _homie._acc). compare.py displays the raw values with delta-vs-derived and flags: - "upstream defect present" when |raw active-power - derived| > 100 W - "upstream defect MAY be fixed" when the delta < 50 W (confirm over sustained samples) - "upstream imported-energy counter still broken" when raw < 0 Live sample at time of writing: firmware active-power offset ~400-450 W vs Kirchhoff — tracking signal works.
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.
No description provided.