Skip to content

Conversation

@andig
Copy link
Member

@andig andig commented Jun 14, 2025

Fix #21747, depends on #21813
Also fixes #21832

Disable solar feed-in when feed-in becomes expensive for the user (i.e. network restriction visible due to feed-in tariff). Implemented by restricting the PV inverter to 0W feed-in power.
Requires supported inverter.

💸 add feed-in visualization to forecast modal
👇 proper handling of negative prices (aligned 0-axis)

TODO

/cc @Maschga wenn Du magst könntest Du hier branchen und einen PR für RCT erstellen und testen.

Out of scope

  • Migrate "battery grid charge" feature to forecast modal
  • Make forecast a top-level page (not a modal) > introduce bottom bar app nav
grid.feedin.webm
Bildschirmfoto 2025-08-25 um 16 59 31 Bildschirmfoto 2025-08-25 um 16 59 39 Bildschirmfoto 2025-08-25 um 17 07 59 Bildschirmfoto 2025-08-25 um 17 08 02 Bildschirmfoto 2025-08-25 um 17 08 20

@andig andig added enhancement New feature or request needs documentation Triggers issue creation in evcc-io/docs labels Jun 14, 2025
@andig andig marked this pull request as draft June 14, 2025 09:52
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @andig - I've reviewed your changes - here's some feedback:

  • The new rateAt helper ignores its t time.Time parameter and always uses time.Now()—update it to use the passed‐in time for consistency and testability.
  • The HTTP endpoints for smart-feed-in disabling (e.g. /smartfeedindisablelimit) use inconsistent casing compared to other routes—standardize on one naming convention for clarity.
  • There’s a lot of duplicated logic between smart-cost and smart-feed-in handling—consider extracting shared behaviour into a common helper to reduce code duplication.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The new rateAt helper ignores its `t time.Time` parameter and always uses `time.Now()`—update it to use the passed‐in time for consistency and testability.
- The HTTP endpoints for smart-feed-in disabling (e.g. `/smartfeedindisablelimit`) use inconsistent casing compared to other routes—standardize on one naming convention for clarity.
- There’s a lot of duplicated logic between smart-cost and smart-feed-in handling—consider extracting shared behaviour into a common helper to reduce code duplication.

## Individual Comments

### Comment 1
<location> `core/site_tariffs.go:177` </location>
<code_context>
+	return site.GetTariff(usage).Type() != api.TariffTypePriceStatic
+}
+
+func rateAt(rates api.Rates, t time.Time) (api.Rate, error) {
+	rate, err := rates.At(time.Now())
+	if len(rates) > 0 && err != nil {
</code_context>

<issue_to_address>
rateAt ignores its time parameter and always uses time.Now()

The function should use the provided `t` parameter in `rates.At` to ensure correct evaluation at the intended time.
</issue_to_address>

### Comment 2
<location> `core/loadpoint/mock.go:925` </location>
<code_context>
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSmartCostLimit", reflect.TypeOf((*MockAPI)(nil).SetSmartCostLimit), limit)
 }

+// SetSmartFeedinLimit mocks base method.
+func (m *MockAPI) SetSmartFeedinLimit(limit *float64) {
+	m.ctrl.T.Helper()
</code_context>

<issue_to_address>
Avoid manual edits in a generated mock file

Regenerate the mock with mockgen to include the new methods, rather than editing the file manually.

Suggested implementation:

```golang

```

After removing the manual edit, you must run `mockgen` to regenerate `core/loadpoint/mock.go` with the updated interface that includes `SetSmartFeedinLimit`. This will ensure the mock is up-to-date and correctly generated.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@andig andig requested a review from premultiply June 14, 2025 10:14
@naltatis
Copy link
Member

Added the option/limit to the forecast dialog since we dont have a global place for pv-based settings. In a future iteration we should promote forecast (together with other charts) to a top level page and also move battery grid charge there. So one place to see all your forecasted data (production, price, ...) and can make decisions based on this. Future optimizer hints or effects could also live there.

@naltatis
Copy link
Member

@andig magst du den Konflikt hier auflösen?

@andig
Copy link
Member Author

andig commented Aug 25, 2025

Done

@naltatis
Copy link
Member

Done

But broken

@naltatis
Copy link
Member

Should be fixed now.

@naltatis
Copy link
Member

Added highlighting of affected time slots. See updated screenshots and video in description 👆

@naltatis
Copy link
Member

Matching limit options:

Bildschirmfoto 2025-08-26 um 17 07 06

vm: shared
script: |
8000;
feedindisablelimitenable:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andig is this the best name? Can we be shorter? feedinDisable, zeroFeedIn, ..?

@naltatis
Copy link
Member

Reflect active limit in energy flow

Bildschirmfoto 2025-08-27 um 14 44 36

@naltatis
Copy link
Member

@andig all done from my side

@naltatis naltatis marked this pull request as ready for review August 27, 2025 13:43
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @naltatis, your pull request is too large to review

@naltatis naltatis assigned andig and unassigned naltatis Aug 27, 2025
@jeffborg
Copy link
Contributor

jeffborg commented Oct 1, 2025

I have a question/maybe a complication about this, currently doing this function from home assistant if evcc isn't active solar and the feed in price is negative (ie: paying to export power to grid) then I flip the load following register on my solar inverter, But from evcc I set the export price to 0 always as I consider evcc to be consuming solar power which has no value and not a negative value.

See the example below the export price is actually -2.9c a kwh but in evcc by using custom forecast the current period is set to 0 just so the charging sessions cost is increasing in price and not decreasing.
image

So in relation to this pr, if evcc can prevent export costing $$ then consideration probably should be given that this is actually 0 in value when calculating charging sessions cost. I'm not seeing anything related to the charging sessions cost in the pr.

@andig
Copy link
Member Author

andig commented Oct 2, 2025

See the example below the export price is actually -2.9c a kwh but in evcc by using custom forecast the current period is set to 0

Why? Forecast wrong? Seems OT here.

@jeffborg
Copy link
Contributor

jeffborg commented Oct 2, 2025

Why? Forecast wrong? Seems OT here.

No -2.9c is the actual feedin price for the current 5 minute interval (IE you pay to export), I just use some jq on the feedin forecast to ensure evcc never sees negative prices for the current feedin interval as that mucks up the charging session cost calculations. (car is not earning money by charging because if it wasn't charging the solar would be automatically curtailed and I wouldn't be paying to export - hence being calculated as 0 is correct) Might be better off discussed on #21747

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backlog Things to do later needs documentation Triggers issue creation in evcc-io/docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FR: UX Visualize feed-in tarrif in forecast screen Feature: zero feed in (when energy prices are negative)

3 participants