Add solar_surplus_wh and solar_active to MQTT output#370
Merged
Conversation
After each control cycle, publish two new topics: - /solar_surplus_wh: expected usable solar surplus in Wh - /solar_production_phase: 'before', 'during', or 'after' Phase detection uses a None sentinel to correctly distinguish "no production in forecast" from "production starting at slot 0", fixing the ambiguity in the wp-feedin heuristic. Production window boundaries track the last non-zero slot to tolerate single-slot forecast gaps. Surplus calculation: - during/before: net production surplus over the forecast window minus free battery capacity (what would be exported/wasted) - after: unreserved stored usable energy minus expected consumption until next solar production starts (what the battery can spare) The corrected (elapsed-time-adjusted) production/consumption arrays are used together with calc_output.reserved_energy from the just-completed optimizer run, so the values are consistent with the control decision. HA MQTT auto-discovery entries added for both sensors. https://claude.ai/code/session_01WQKwRRnW55Tr2mBkKao573
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds MQTT reporting for expected solar surplus and solar production phase after optimizer runs, helping downstream MQTT/HA consumers react to PV availability.
Changes:
- Adds core calculation for solar phase and surplus energy.
- Publishes two new MQTT topics for surplus Wh and production phase.
- Adds Home Assistant discovery entries for the new sensors.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/batcontrol/core.py |
Computes and publishes solar phase/surplus after optimization. |
src/batcontrol/mqtt_api.py |
Adds MQTT publishers and HA discovery entries for the new sensors. |
Fix surplus calculation for during/before phase: sum the net energy balance over the entire production window (production minus consumption) instead of only counting slots where production exceeds consumption. Positive consumption slots in the window now correctly reduce the reported surplus. Fix free_capacity and stored_usable_energy consistency: pass calc_input.free_capacity and calc_input.stored_usable_energy into the helper so the published values are based on the same inverter snapshot as the optimizer decision, avoiding a second inverter read. Add tests/batcontrol/test_solar_surplus.py: 19 focused tests covering phase detection (during/before/after, gaps, 15-min resolution) and surplus calculation for all three phases including edge cases (fits in battery, exceeds capacity, negative surplus clamped to zero, reserved energy, 15-min scaling). Extend tests/batcontrol/test_mqtt_api.py: 8 tests covering publish_solar_surplus (topic, format, zero, disconnected) and publish_production_phase (all three values, disconnected). https://claude.ai/code/session_01WQKwRRnW55Tr2mBkKao573
… scoping Three bugs fixed in _compute_solar_surplus_and_phase: - Remove wh_per_slot multiplier (arrays are already Wh/slot, not W) - Use first production window only (not last slot in multi-day forecast) - Replace reserved_energy/stored_usable with forecast-based bridge calculation New formula for 'before'/'after': expected solar overflow at end of next production window = max(0, solar_net_next - free_capacity - bridge_wh), where bridge_wh is forecast consumption until solar starts. Identical formula for both phases; phase label differs only by threshold distance. Add before_phase_threshold_h (default 4h) to battery_control_expert config.
'before' and 'after' used identical formulas; only the label differed. Replace the 3-state string with a binary signal: solar_active=True iff production[0] > 0. Drops the unused before_phase_threshold_h config. MQTT topic renamed: solar_production_phase -> solar_active (binary_sensor in HA discovery). Consumers should switch to solar_surplus_wh + solar_active.
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.
After each control cycle, publish two new MQTT topics:
/solar_surplus_wh— expected solar overflow in Wh (energy that would be fed to grid)/solar_active— boolean,trueiff solar is producing in the current slot (binary_sensor in HA discovery, retained)Surplus formula
When solar is active (
solar_active = true,production[0] > 0):Covers the first production window only (scan stops at the first zero slot after production starts, preventing multi-day forecast contamination).
When solar is inactive (
solar_active = false):Answers: "given current battery state and expected night consumption, how much of tomorrow's solar production will overflow?" — rein forecast-basiert, ohne
reserved_energyoderstored_usable_energy.If no solar exists in the forecast,
surplus_wh = 0.Key implementation details
wh_per_slotscaling needed, correct at 15-min and 60-min resolution.free_capacityis taken fromcalc_input(same snapshot as the optimizer decision).before/during/after) was collapsed to a boolean:beforeandafterused identical formulas; only the label differed.before_phase_threshold_hconfig key — the boolean needs no threshold.https://claude.ai/code/session_01WQKwRRnW55Tr2mBkKao573