Migrate optimizer (BC) (#28088)
This commit is contained in:
parent
d8084ed71a
commit
c9876e38ae
4 changed files with 31 additions and 31 deletions
|
|
@ -11,7 +11,6 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
evopt "github.com/andig/evopt/client"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/core/keys"
|
||||
"github.com/evcc-io/evcc/core/loadpoint"
|
||||
|
|
@ -21,6 +20,7 @@ import (
|
|||
"github.com/evcc-io/evcc/util/config"
|
||||
"github.com/evcc-io/evcc/util/request"
|
||||
"github.com/evcc-io/evcc/util/sponsor"
|
||||
optimizer "github.com/evcc-io/optimizer/client"
|
||||
"github.com/jinzhu/now"
|
||||
"github.com/samber/lo"
|
||||
"golang.org/x/exp/constraints"
|
||||
|
|
@ -110,7 +110,7 @@ func (site *Site) optimizerUpdateAsync() {
|
|||
}
|
||||
|
||||
func (site *Site) optimizerUpdate(battery []types.Measurement) error {
|
||||
uri := os.Getenv("EVOPT_URI")
|
||||
uri := os.Getenv("OPTIMIZER_URI")
|
||||
if uri == "" {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -156,14 +156,14 @@ func (site *Site) optimizerUpdate(battery []types.Measurement) error {
|
|||
ft = prorate(scaleAndPrune(solarEnergy, 1, minLen), firstSlotDuration)
|
||||
}
|
||||
|
||||
req := evopt.OptimizationInput{
|
||||
Strategy: evopt.OptimizerStrategy{
|
||||
ChargingStrategy: evopt.OptimizerStrategyChargingStrategyChargeBeforeExport, // AttenuateGridPeaks
|
||||
DischargingStrategy: evopt.OptimizerStrategyDischargingStrategyDischargeBeforeImport,
|
||||
req := optimizer.OptimizationInput{
|
||||
Strategy: optimizer.OptimizerStrategy{
|
||||
ChargingStrategy: optimizer.OptimizerStrategyChargingStrategyChargeBeforeExport, // AttenuateGridPeaks
|
||||
DischargingStrategy: optimizer.OptimizerStrategyDischargingStrategyDischargeBeforeImport,
|
||||
},
|
||||
EtaC: eta,
|
||||
EtaD: eta,
|
||||
TimeSeries: evopt.TimeSeries{
|
||||
TimeSeries: optimizer.TimeSeries{
|
||||
Dt: dt,
|
||||
Gt: prorate(gt, firstSlotDuration),
|
||||
Ft: ft,
|
||||
|
|
@ -181,14 +181,14 @@ func (site *Site) optimizerUpdate(battery []types.Measurement) error {
|
|||
|
||||
if site.circuit != nil {
|
||||
if pMaxImp := site.circuit.GetMaxPower(); pMaxImp > 0 {
|
||||
req.Grid = evopt.GridConfig{
|
||||
req.Grid = optimizer.GridConfig{
|
||||
// hard grid import limit if no price penalty is set by PrcPExcImp
|
||||
PMaxImp: float32(pMaxImp),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add := func(battery evopt.BatteryConfig, detail batteryDetail) {
|
||||
add := func(battery optimizer.BatteryConfig, detail batteryDetail) {
|
||||
battery.PA = pa
|
||||
req.Batteries = append(req.Batteries, battery)
|
||||
details.BatteryDetails = append(details.BatteryDetails, detail)
|
||||
|
|
@ -220,7 +220,7 @@ func (site *Site) optimizerUpdate(battery []types.Measurement) error {
|
|||
httpClient := request.NewClient(site.log)
|
||||
httpClient.Timeout = 30 * time.Second
|
||||
|
||||
apiClient, err := evopt.NewClientWithResponses(uri, evopt.WithHTTPClient(httpClient))
|
||||
apiClient, err := optimizer.NewClientWithResponses(uri, optimizer.WithHTTPClient(httpClient))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -240,9 +240,9 @@ func (site *Site) optimizerUpdate(battery []types.Measurement) error {
|
|||
}
|
||||
|
||||
site.publish("evopt", struct {
|
||||
Req evopt.OptimizationInput `json:"req"`
|
||||
Res evopt.OptimizationResult `json:"res"`
|
||||
Details requestDetails `json:"details"`
|
||||
Req optimizer.OptimizationInput `json:"req"`
|
||||
Res optimizer.OptimizationResult `json:"res"`
|
||||
Details requestDetails `json:"details"`
|
||||
}{
|
||||
Req: req,
|
||||
Res: *resp.JSON200,
|
||||
|
|
@ -275,7 +275,7 @@ func (site *Site) optimizerUpdate(battery []types.Measurement) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (site *Site) addBatteryForecastTotals(req []evopt.BatteryConfig, resp []evopt.BatteryResult) *types.BatteryForecast {
|
||||
func (site *Site) addBatteryForecastTotals(req []optimizer.BatteryConfig, resp []optimizer.BatteryResult) *types.BatteryForecast {
|
||||
if len(resp) == 0 || len(resp[0].StateOfCharge) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -303,8 +303,8 @@ func (site *Site) addBatteryForecastTotals(req []evopt.BatteryConfig, resp []evo
|
|||
return &res
|
||||
}
|
||||
|
||||
func (site *Site) batteryForecastFullAndEmptySlots(req []evopt.BatteryConfig, resp []evopt.BatteryResult) (int, int) {
|
||||
matchSlot := func(fun func(soc float32, bat evopt.BatteryConfig) bool) int {
|
||||
func (site *Site) batteryForecastFullAndEmptySlots(req []optimizer.BatteryConfig, resp []optimizer.BatteryResult) (int, int) {
|
||||
matchSlot := func(fun func(soc float32, bat optimizer.BatteryConfig) bool) int {
|
||||
NEXT:
|
||||
for i := range resp[0].StateOfCharge {
|
||||
for batIdx := range req {
|
||||
|
|
@ -317,18 +317,18 @@ func (site *Site) batteryForecastFullAndEmptySlots(req []evopt.BatteryConfig, re
|
|||
return -1
|
||||
}
|
||||
|
||||
fullSlot := matchSlot(func(soc float32, bat evopt.BatteryConfig) bool {
|
||||
fullSlot := matchSlot(func(soc float32, bat optimizer.BatteryConfig) bool {
|
||||
return soc >= bat.SMax
|
||||
})
|
||||
emptySlot := matchSlot(func(soc float32, bat evopt.BatteryConfig) bool {
|
||||
emptySlot := matchSlot(func(soc float32, bat optimizer.BatteryConfig) bool {
|
||||
return soc <= bat.SMin
|
||||
})
|
||||
|
||||
return fullSlot, emptySlot
|
||||
}
|
||||
|
||||
func (site *Site) loadpointRequest(lp loadpoint.API, minLen int, firstSlotDuration time.Duration, grid api.Rates) (evopt.BatteryConfig, batteryDetail) {
|
||||
bat := evopt.BatteryConfig{
|
||||
func (site *Site) loadpointRequest(lp loadpoint.API, minLen int, firstSlotDuration time.Duration, grid api.Rates) (optimizer.BatteryConfig, batteryDetail) {
|
||||
bat := optimizer.BatteryConfig{
|
||||
ChargeFromGrid: true,
|
||||
CMin: float32(lp.EffectiveMinPower()),
|
||||
CMax: float32(lp.EffectiveMaxPower()),
|
||||
|
|
@ -407,8 +407,8 @@ func (site *Site) loadpointRequest(lp loadpoint.API, minLen int, firstSlotDurati
|
|||
return bat, detail
|
||||
}
|
||||
|
||||
func (site *Site) batteryRequest(dev config.Device[api.Meter], b types.Measurement, grid api.Rates, minLen int, firstSlotDuration time.Duration) (evopt.BatteryConfig, batteryDetail) {
|
||||
bat := evopt.BatteryConfig{
|
||||
func (site *Site) batteryRequest(dev config.Device[api.Meter], b types.Measurement, grid api.Rates, minLen int, firstSlotDuration time.Duration) (optimizer.BatteryConfig, batteryDetail) {
|
||||
bat := optimizer.BatteryConfig{
|
||||
CMax: batteryPower,
|
||||
DMax: batteryPower,
|
||||
SInitial: float32(*b.Capacity * *b.Soc * 10), // Wh
|
||||
|
|
@ -633,7 +633,7 @@ func scaleAndPrune(rates api.Rates, div float64, maxLen int) []float32 {
|
|||
return res
|
||||
}
|
||||
|
||||
func (site *Site) applyPlanGoal(lp loadpoint.API, bat *evopt.BatteryConfig, minLen int) {
|
||||
func (site *Site) applyPlanGoal(lp loadpoint.API, bat *optimizer.BatteryConfig, minLen int) {
|
||||
goal, socBased := lp.GetPlanGoal()
|
||||
if goal <= 0 {
|
||||
return
|
||||
|
|
@ -719,8 +719,8 @@ func (site *Site) applyBatteryGridChargeLimit(cMax float32, grid api.Rates, minL
|
|||
}
|
||||
|
||||
// apiError extracts error message from optimizer API response
|
||||
func apiError(resp *evopt.PostOptimizeChargeScheduleResponse) error {
|
||||
var errObj *evopt.Error
|
||||
func apiError(resp *optimizer.PostOptimizeChargeScheduleResponse) error {
|
||||
var errObj *optimizer.Error
|
||||
switch resp.StatusCode() {
|
||||
case http.StatusBadRequest:
|
||||
errObj = resp.JSON400
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
evopt "github.com/andig/evopt/client"
|
||||
"github.com/benbjohnson/clock"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/core/loadpoint"
|
||||
"github.com/evcc-io/evcc/core/metrics"
|
||||
"github.com/evcc-io/evcc/server/db"
|
||||
optimizer "github.com/evcc-io/optimizer/client"
|
||||
"github.com/jinzhu/now"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -114,7 +114,7 @@ func TestLoadpointProfile(t *testing.T) {
|
|||
func TestBatteryForecastTotals(t *testing.T) {
|
||||
site := new(Site)
|
||||
|
||||
req := []evopt.BatteryConfig{
|
||||
req := []optimizer.BatteryConfig{
|
||||
{SMax: 80},
|
||||
{SMax: 80},
|
||||
}
|
||||
|
|
@ -164,7 +164,7 @@ func TestBatteryForecastTotals(t *testing.T) {
|
|||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
resp := []evopt.BatteryResult{
|
||||
resp := []optimizer.BatteryResult{
|
||||
{StateOfCharge: tc.bat1},
|
||||
{StateOfCharge: tc.bat2},
|
||||
}
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -8,7 +8,6 @@ require (
|
|||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/PuerkitoBio/goquery v1.11.0
|
||||
github.com/WulfgarW/sensonet v0.0.7
|
||||
github.com/andig/evopt v0.0.0-20260202080401-5c7f3dae3896
|
||||
github.com/andig/go-powerwall v0.2.1-0.20230808194509-dd70cdb6e140
|
||||
github.com/andig/gosunspec v0.0.0-20240918203654-860ce51d602b
|
||||
github.com/andig/mbserver v0.0.0-20230310211055-1d29cbb5820e
|
||||
|
|
@ -33,6 +32,7 @@ require (
|
|||
github.com/enbility/ship-go v0.6.0
|
||||
github.com/enbility/spine-go v0.7.0
|
||||
github.com/evcc-io/openapi-mcp v0.6.0
|
||||
github.com/evcc-io/optimizer v0.0.0-20260310135618-de48ea1cf9f6
|
||||
github.com/evcc-io/rct v0.1.2-0.20260222151045-de2e4108c99c
|
||||
github.com/evcc-io/tesla-proxy-client v0.0.0-20240221194046-4168b3759701
|
||||
github.com/fatih/structs v1.1.0
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -33,8 +33,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/andig/evopt v0.0.0-20260202080401-5c7f3dae3896 h1:veq0GvT15cv7124nu4XvhsyFIrYcTw6E2/FUVs+AXRY=
|
||||
github.com/andig/evopt v0.0.0-20260202080401-5c7f3dae3896/go.mod h1:C05cTe1ffvaip2xNNHMJSy/OtGT/NH1sXQgmV/7be8k=
|
||||
github.com/andig/go-powerwall v0.2.1-0.20230808194509-dd70cdb6e140 h1:C93T8vg7CN4Q4BBDbBMOvBoTYBA+CaBEvlY2SZF8aa0=
|
||||
github.com/andig/go-powerwall v0.2.1-0.20230808194509-dd70cdb6e140/go.mod h1:Xk09mD+7RTCuuHMX5RxlqgEUeh9oZdIX0rL0qiY6l/4=
|
||||
github.com/andig/gosunspec v0.0.0-20240918203654-860ce51d602b h1:81UMfM949I7StrRay7YDUZazY8M1u/JHkzwcFEjiilQ=
|
||||
|
|
@ -201,6 +199,8 @@ github.com/evcc-io/ocpp-go v0.0.0-20251212212612-b7f92ee0443b h1:5vFr7wOwoi5ylyb
|
|||
github.com/evcc-io/ocpp-go v0.0.0-20251212212612-b7f92ee0443b/go.mod h1:2kcukDdhui4u730VfnYVWuwzDLgw+mBRGDir/QAyBhg=
|
||||
github.com/evcc-io/openapi-mcp v0.6.0 h1:cq8CWG+3gNQ9ID0ZE8MoDHZxgdJmBZ1fFyt5xAfTRfA=
|
||||
github.com/evcc-io/openapi-mcp v0.6.0/go.mod h1:YyOx4zwr6xVUcchAETHERZ+75cZMIrdcjVIZFwBlE1Q=
|
||||
github.com/evcc-io/optimizer v0.0.0-20260310135618-de48ea1cf9f6 h1:W4j2gpIs5d5c1lLS4cD0/rsZYuluPS3KJoGXXANBBYY=
|
||||
github.com/evcc-io/optimizer v0.0.0-20260310135618-de48ea1cf9f6/go.mod h1:cHMeq6GfoXQ8LxqY4LH1wn/hrgYEn+ka5RPI1CF37SY=
|
||||
github.com/evcc-io/rct v0.1.2-0.20260222151045-de2e4108c99c h1:bmtzp2QjwIylg7QuAAxclew4rd/G6Pub5MkTkUTjV/w=
|
||||
github.com/evcc-io/rct v0.1.2-0.20260222151045-de2e4108c99c/go.mod h1:n6MTBU36QOadGlxxiADu86VaT5l0eYdbmFBHF14AD/s=
|
||||
github.com/evcc-io/tesla-proxy-client v0.0.0-20240221194046-4168b3759701 h1:3JplY3KS6KMDVDNAU+3+KWmSWmoHIU34qwuIpW6SiHk=
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue