[#101] Add phase protection logic + offline test suites#147
Open
nickles-lee wants to merge 15 commits into
Open
[#101] Add phase protection logic + offline test suites#147nickles-lee wants to merge 15 commits into
nickles-lee wants to merge 15 commits into
Conversation
added 15 commits
June 3, 2026 12:42
…ies' into 101-phase-protection-peak-shaving
… & command_limits_available handling
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.
Summary
Closes #101.
This PR adds optional per-phase peak-shaving protection on top of the existing aggregate import/export peak-shaving behavior.
When enabled and usable phase data is available, the controller can react when an individual phase exceeds the configured per-phase power limit, even if the aggregate grid value still looks safe.
What changed
grid_power_phase.L1/L2/L3.Standby / peak shave.Stacked PR note
This PR is stacked on top of #139.
#139 contains the phase assignment / phase exposure groundwork. This PR intentionally focuses only on the #101 phase-protection logic and offline test coverage. Please avoid reviewing #102-scoped changes here; review this PR as the delta from the head of
102-phase-assignments-for-batteriesto the head of101-phase-protection-peak-shaving.Suggested review compare:
Range-diff from the #139 stack branch to this branch:
Compatibility
Existing behavior remains unchanged when phase protection is disabled, phase sensors are unavailable, or no batteries are assigned to phases.
Per-phase protection only acts when all of the following are true:
Full stopis intentionally not preempted.Testing
Offline Node-RED flow test coverage was added for phase-protection behavior.
Validated locally on this branch:
Also verified that the phase-protection tests fail when run against
main, where the phase-protection logic does not exist:This confirms the tests are not simply passing vacuously on branches without the feature.
Regression checks were also run against earlier draft commits in this branch to make sure the test suite catches prior unwanted behavior, including missing guard logic, unfair first-fit allocation, missing priority preservation, and missing allocator helpers.
Real-world testing / safety notes
This is an experimental control feature. It does not come with any warranty, guarantee, or promise that your phase fuse will not blow. If you're worried about this, set a wider safety margin on the per-phase limit to account for any spikes that will take some time for the batteries to respond to.
This logic is software-based peak shaving, not a replacement for correct electrical design, breaker sizing, phase-aware charger limiting, inverter limits, or professional installation checks.
If you test this branch on a real installation:
This improves the safety of your system & lets you run "hotter", but it does not make the system safe in the way a 25A circuit breaker on each phase would.
Real-World Testing
I have been running this branch in my house for around 1 to 2 weeks without incident, with no PV + heavier loading on Phase 3. If I ran the Charge strategy with the power limits I now have set, one of the main fuses would have cooked.
Some graphs:
Approx. 1 day view:

A more zoomed-in view of a period where phase 3 is running at full load:

Start of a brief overload to 32A, caused by an appliance switching on while the batteries had Phase 3 fully loaded:

End of the overload, 10s later

Note that I've validated phase protection during the time period where the batteries are charging. I haven't tested phase protection when the batteries are on standby / not actively charging.