Skip to content

fix: SolarStopTimer unreachable in multi-node solar mode#119

Merged
basmeerman merged 1 commit intomasterfrom
fix/solar-stop-timer-multi-node
Mar 27, 2026
Merged

fix: SolarStopTimer unreachable in multi-node solar mode#119
basmeerman merged 1 commit intomasterfrom
fix/solar-stop-timer-multi-node

Conversation

@basmeerman
Copy link
Copy Markdown
Owner

Summary

  • Fix: Remove ActiveEVSE multiplier from SolarStopTimer threshold in evse_state_machine.c, making it based on a single-EVSE minimum instead of scaling with the number of active nodes
  • Root cause: Upstream formula (ActiveEVSE * MinCurrent * Phases - StartCurrent) * 10 made the threshold unreachable in multi-node setups (32A for 2 EVSEs, 68A for 4, 140A for 8) — priority scheduling already handles which cars charge
  • Tests: 24 new tests in test_multi_node_solar.c covering shortage detection, timer lifecycle, threshold boundaries, capacity tariff interaction, and power-delivery-vs-session verification

Bug context

Real-world issue: secondary EVSE kept charging at 6A (MinCurrent) in solar mode with no solar surplus. Debug log showed SolarStopTimer: 0 (never started) because mains import (20.7A) was below the 2-EVSE threshold (32A). The bug exists in upstream (dingo35/SmartEVSE-3.5, commit 94ca08e).

What changed

One-line fix in evse_state_machine.c:910:

// Before (buggy — threshold scales with ActiveEVSE):
ctx->Isum > (ActiveEVSE * MinCurrent * Phases - StartCurrent) * 10

// After (fixed — single-EVSE threshold):
ctx->Isum > (MinCurrent * Phases - StartCurrent) * 10

Single-EVSE behavior is unchanged (ActiveEVSE was 1).

Test plan

  • 24 new tests in test_multi_node_solar.c — all pass
  • Full native test suite (49 suites) — all pass
  • Address + UB sanitizers — clean
  • cppcheck static analysis — clean
  • ESP32 firmware build — success (86.2% flash, 24.0% RAM)
  • CH32 firmware build — success (71.3% flash, 22.1% RAM)

New test groups

Group Tests Covers
Multi-node solar shortage 5 Timer start above/below threshold, priority pausing, NO_SUN flags
Solar surplus scenarios 2 Both-charge, marginal surplus
SolarStopTimer lifecycle 4 No-restart, surplus-clears, startup-suppression, boundary
Mode consistency 2 Solar vs Normal vs Smart distribution
Edge cases 3 Node offline, ImportCurrent, NoCurrent threshold
Solar + Capacity Tariff 4 Tight headroom, no surplus + headroom, disabled, negative
Power vs Session lifecycle 3 C→C1 preserves AccessStatus, LESS_6A recovery, full pause cycle

🤖 Generated with Claude Code

The SolarStopTimer threshold formula scaled linearly with ActiveEVSE,
making it impossible to trigger in multi-node setups. With 2 EVSEs on
3-phase at 6A min, the threshold was 32A — but the mains meter only
showed ~20A because solar partially offset EV consumption. Result:
secondary nodes kept charging at MinCurrent indefinitely despite no
solar surplus.

Root cause: upstream commit 94ca08e introduced
  Isum > (ActiveEVSE * MinCurrent * Phases - StartCurrent) * 10
which is correct for single-EVSE but scales the threshold unreachably
high for multi-node (68A for 4 EVSEs, 140A for 8).

Fix: remove ActiveEVSE from the threshold, using single-EVSE minimum:
  Isum > (MinCurrent * Phases - StartCurrent) * 10
This is correct because priority scheduling already handles which cars
charge and which are paused. The SolarStopTimer should only fire when
there isn't enough solar for even one car at MinCurrent.

Single-EVSE behavior is unchanged (ActiveEVSE was 1).

Adds 24 new tests in test_multi_node_solar.c covering:
- Multi-node solar shortage and SolarStopTimer lifecycle
- Threshold boundary verification (above/below)
- Solar + capacity tariff interaction
- Power delivery pause vs session/OCPP lifecycle
- Mode consistency (Solar vs Normal vs Smart)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@basmeerman basmeerman merged commit c63ee1e into master Mar 27, 2026
13 checks passed
@basmeerman basmeerman deleted the fix/solar-stop-timer-multi-node branch March 27, 2026 10:00
basmeerman added a commit that referenced this pull request Mar 27, 2026
Test infrastructure grew from 47→50 suites and 1,046→1,096 tests after
merging multi-node solar fix (PR #119, +24 tests) and mode sync fix
(PR #121, +8 tests). Updated all documentation references:

- CLAUDE.md, README.md, CONTRIBUTING.md: test count references
- docs/quality.md: 4 occurrences of test metrics
- docs/upstream-differences.md: added both fixes as upstream divergences
- docs/manual-test-plan.md: test count reference
- test-specification.md: regenerated (70 features, 1,082 scenarios)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant