Add loadpoint prioritisation (#6107)

This commit is contained in:
andig 2023-02-19 15:36:18 +01:00 • committed by GitHub
parent c65f7270a9
commit ccb1338d90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 638 additions and 2 deletions

View file

@ -103,6 +103,7 @@ type Loadpoint struct {
Mode api.ChargeMode `mapstructure:"mode"` // Charge mode, guarded by mutex
Title_ string `mapstructure:"title"` // UI title
Priority_ int `mapstructure:"priority"` // Priority
ConfiguredPhases int `mapstructure:"phases"` // Charger configured phase mode 0/1/3
ChargerRef string `mapstructure:"charger"` // Charger reference
VehicleRef string `mapstructure:"vehicle"` // Vehicle reference

View file

@ -6,6 +6,8 @@ import (
"github.com/evcc-io/evcc/api"
)
//go:generate mockgen -package loadpoint -destination mock.go -mock_names API=MockAPI github.com/evcc-io/evcc/core/loadpoint API
// Controller gives access to loadpoint
type Controller interface {
LoadpointControl(API)
@ -15,6 +17,7 @@ type Controller interface {
type API interface {
// Title returns the defined loadpoint title
Title() string
Priority() int
//
// status
@ -76,6 +79,8 @@ type API interface {
HasChargeMeter() bool
// GetChargePower returns the current charging power
GetChargePower() float64
// GetChargePowerFlexibility returns the flexible amount of current charging power
GetChargePowerFlexibility() float64
// GetMinCurrent returns the min charging current
GetMinCurrent() float64
// SetMinCurrent sets the min charging current

520
core/loadpoint/mock.go Normal file
View file

@ -0,0 +1,520 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/evcc-io/evcc/core/loadpoint (interfaces: API)
// Package loadpoint is a generated GoMock package.
package loadpoint
import (
reflect "reflect"
time "time"
api "github.com/evcc-io/evcc/api"
gomock "github.com/golang/mock/gomock"
)
// MockAPI is a mock of API interface.
type MockAPI struct {
ctrl *gomock.Controller
recorder *MockAPIMockRecorder
}
// MockAPIMockRecorder is the mock recorder for MockAPI.
type MockAPIMockRecorder struct {
mock *MockAPI
}
// NewMockAPI creates a new mock instance.
func NewMockAPI(ctrl *gomock.Controller) *MockAPI {
mock := &MockAPI{ctrl: ctrl}
mock.recorder = &MockAPIMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockAPI) EXPECT() *MockAPIMockRecorder {
return m.recorder
}
// GetChargePower mocks base method.
func (m *MockAPI) GetChargePower() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetChargePower")
ret0, _ := ret[0].(float64)
return ret0
}
// GetChargePower indicates an expected call of GetChargePower.
func (mr *MockAPIMockRecorder) GetChargePower() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChargePower", reflect.TypeOf((*MockAPI)(nil).GetChargePower))
}
// GetChargePowerFlexibility mocks base method.
func (m *MockAPI) GetChargePowerFlexibility() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetChargePowerFlexibility")
ret0, _ := ret[0].(float64)
return ret0
}
// GetChargePowerFlexibility indicates an expected call of GetChargePowerFlexibility.
func (mr *MockAPIMockRecorder) GetChargePowerFlexibility() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChargePowerFlexibility", reflect.TypeOf((*MockAPI)(nil).GetChargePowerFlexibility))
}
// GetDisableThreshold mocks base method.
func (m *MockAPI) GetDisableThreshold() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDisableThreshold")
ret0, _ := ret[0].(float64)
return ret0
}
// GetDisableThreshold indicates an expected call of GetDisableThreshold.
func (mr *MockAPIMockRecorder) GetDisableThreshold() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDisableThreshold", reflect.TypeOf((*MockAPI)(nil).GetDisableThreshold))
}
// GetEnableThreshold mocks base method.
func (m *MockAPI) GetEnableThreshold() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetEnableThreshold")
ret0, _ := ret[0].(float64)
return ret0
}
// GetEnableThreshold indicates an expected call of GetEnableThreshold.
func (mr *MockAPIMockRecorder) GetEnableThreshold() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEnableThreshold", reflect.TypeOf((*MockAPI)(nil).GetEnableThreshold))
}
// GetMaxCurrent mocks base method.
func (m *MockAPI) GetMaxCurrent() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMaxCurrent")
ret0, _ := ret[0].(float64)
return ret0
}
// GetMaxCurrent indicates an expected call of GetMaxCurrent.
func (mr *MockAPIMockRecorder) GetMaxCurrent() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaxCurrent", reflect.TypeOf((*MockAPI)(nil).GetMaxCurrent))
}
// GetMaxPower mocks base method.
func (m *MockAPI) GetMaxPower() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMaxPower")
ret0, _ := ret[0].(float64)
return ret0
}
// GetMaxPower indicates an expected call of GetMaxPower.
func (mr *MockAPIMockRecorder) GetMaxPower() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaxPower", reflect.TypeOf((*MockAPI)(nil).GetMaxPower))
}
// GetMinCurrent mocks base method.
func (m *MockAPI) GetMinCurrent() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMinCurrent")
ret0, _ := ret[0].(float64)
return ret0
}
// GetMinCurrent indicates an expected call of GetMinCurrent.
func (mr *MockAPIMockRecorder) GetMinCurrent() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMinCurrent", reflect.TypeOf((*MockAPI)(nil).GetMinCurrent))
}
// GetMinPower mocks base method.
func (m *MockAPI) GetMinPower() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMinPower")
ret0, _ := ret[0].(float64)
return ret0
}
// GetMinPower indicates an expected call of GetMinPower.
func (mr *MockAPIMockRecorder) GetMinPower() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMinPower", reflect.TypeOf((*MockAPI)(nil).GetMinPower))
}
// GetMinSoc mocks base method.
func (m *MockAPI) GetMinSoc() int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMinSoc")
ret0, _ := ret[0].(int)
return ret0
}
// GetMinSoc indicates an expected call of GetMinSoc.
func (mr *MockAPIMockRecorder) GetMinSoc() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMinSoc", reflect.TypeOf((*MockAPI)(nil).GetMinSoc))
}
// GetMode mocks base method.
func (m *MockAPI) GetMode() api.ChargeMode {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMode")
ret0, _ := ret[0].(api.ChargeMode)
return ret0
}
// GetMode indicates an expected call of GetMode.
func (mr *MockAPIMockRecorder) GetMode() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMode", reflect.TypeOf((*MockAPI)(nil).GetMode))
}
// GetPhases mocks base method.
func (m *MockAPI) GetPhases() int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPhases")
ret0, _ := ret[0].(int)
return ret0
}
// GetPhases indicates an expected call of GetPhases.
func (mr *MockAPIMockRecorder) GetPhases() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPhases", reflect.TypeOf((*MockAPI)(nil).GetPhases))
}
// GetPlan mocks base method.
func (m *MockAPI) GetPlan(arg0 time.Time, arg1 float64) (time.Duration, api.Rates, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPlan", arg0, arg1)
ret0, _ := ret[0].(time.Duration)
ret1, _ := ret[1].(api.Rates)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
// GetPlan indicates an expected call of GetPlan.
func (mr *MockAPIMockRecorder) GetPlan(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPlan", reflect.TypeOf((*MockAPI)(nil).GetPlan), arg0, arg1)
}
// GetPlannerUnit mocks base method.
func (m *MockAPI) GetPlannerUnit() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPlannerUnit")
ret0, _ := ret[0].(string)
return ret0
}
// GetPlannerUnit indicates an expected call of GetPlannerUnit.
func (mr *MockAPIMockRecorder) GetPlannerUnit() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPlannerUnit", reflect.TypeOf((*MockAPI)(nil).GetPlannerUnit))
}
// GetRemainingDuration mocks base method.
func (m *MockAPI) GetRemainingDuration() time.Duration {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRemainingDuration")
ret0, _ := ret[0].(time.Duration)
return ret0
}
// GetRemainingDuration indicates an expected call of GetRemainingDuration.
func (mr *MockAPIMockRecorder) GetRemainingDuration() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRemainingDuration", reflect.TypeOf((*MockAPI)(nil).GetRemainingDuration))
}
// GetRemainingEnergy mocks base method.
func (m *MockAPI) GetRemainingEnergy() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRemainingEnergy")
ret0, _ := ret[0].(float64)
return ret0
}
// GetRemainingEnergy indicates an expected call of GetRemainingEnergy.
func (mr *MockAPIMockRecorder) GetRemainingEnergy() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRemainingEnergy", reflect.TypeOf((*MockAPI)(nil).GetRemainingEnergy))
}
// GetStatus mocks base method.
func (m *MockAPI) GetStatus() api.ChargeStatus {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetStatus")
ret0, _ := ret[0].(api.ChargeStatus)
return ret0
}
// GetStatus indicates an expected call of GetStatus.
func (mr *MockAPIMockRecorder) GetStatus() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStatus", reflect.TypeOf((*MockAPI)(nil).GetStatus))
}
// GetTargetEnergy mocks base method.
func (m *MockAPI) GetTargetEnergy() float64 {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetTargetEnergy")
ret0, _ := ret[0].(float64)
return ret0
}
// GetTargetEnergy indicates an expected call of GetTargetEnergy.
func (mr *MockAPIMockRecorder) GetTargetEnergy() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTargetEnergy", reflect.TypeOf((*MockAPI)(nil).GetTargetEnergy))
}
// GetTargetSoc mocks base method.
func (m *MockAPI) GetTargetSoc() int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetTargetSoc")
ret0, _ := ret[0].(int)
return ret0
}
// GetTargetSoc indicates an expected call of GetTargetSoc.
func (mr *MockAPIMockRecorder) GetTargetSoc() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTargetSoc", reflect.TypeOf((*MockAPI)(nil).GetTargetSoc))
}
// GetTargetTime mocks base method.
func (m *MockAPI) GetTargetTime() time.Time {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetTargetTime")
ret0, _ := ret[0].(time.Time)
return ret0
}
// GetTargetTime indicates an expected call of GetTargetTime.
func (mr *MockAPIMockRecorder) GetTargetTime() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTargetTime", reflect.TypeOf((*MockAPI)(nil).GetTargetTime))
}
// GetVehicle mocks base method.
func (m *MockAPI) GetVehicle() api.Vehicle {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetVehicle")
ret0, _ := ret[0].(api.Vehicle)
return ret0
}
// GetVehicle indicates an expected call of GetVehicle.
func (mr *MockAPIMockRecorder) GetVehicle() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVehicle", reflect.TypeOf((*MockAPI)(nil).GetVehicle))
}
// HasChargeMeter mocks base method.
func (m *MockAPI) HasChargeMeter() bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HasChargeMeter")
ret0, _ := ret[0].(bool)
return ret0
}
// HasChargeMeter indicates an expected call of HasChargeMeter.
func (mr *MockAPIMockRecorder) HasChargeMeter() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasChargeMeter", reflect.TypeOf((*MockAPI)(nil).HasChargeMeter))
}
// Priority mocks base method.
func (m *MockAPI) Priority() int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Priority")
ret0, _ := ret[0].(int)
return ret0
}
// Priority indicates an expected call of Priority.
func (mr *MockAPIMockRecorder) Priority() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Priority", reflect.TypeOf((*MockAPI)(nil).Priority))
}
// RemoteControl mocks base method.
func (m *MockAPI) RemoteControl(arg0 string, arg1 RemoteDemand) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "RemoteControl", arg0, arg1)
}
// RemoteControl indicates an expected call of RemoteControl.
func (mr *MockAPIMockRecorder) RemoteControl(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoteControl", reflect.TypeOf((*MockAPI)(nil).RemoteControl), arg0, arg1)
}
// SetDisableThreshold mocks base method.
func (m *MockAPI) SetDisableThreshold(arg0 float64) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetDisableThreshold", arg0)
}
// SetDisableThreshold indicates an expected call of SetDisableThreshold.
func (mr *MockAPIMockRecorder) SetDisableThreshold(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDisableThreshold", reflect.TypeOf((*MockAPI)(nil).SetDisableThreshold), arg0)
}
// SetEnableThreshold mocks base method.
func (m *MockAPI) SetEnableThreshold(arg0 float64) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetEnableThreshold", arg0)
}
// SetEnableThreshold indicates an expected call of SetEnableThreshold.
func (mr *MockAPIMockRecorder) SetEnableThreshold(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetEnableThreshold", reflect.TypeOf((*MockAPI)(nil).SetEnableThreshold), arg0)
}
// SetMaxCurrent mocks base method.
func (m *MockAPI) SetMaxCurrent(arg0 float64) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetMaxCurrent", arg0)
}
// SetMaxCurrent indicates an expected call of SetMaxCurrent.
func (mr *MockAPIMockRecorder) SetMaxCurrent(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMaxCurrent", reflect.TypeOf((*MockAPI)(nil).SetMaxCurrent), arg0)
}
// SetMinCurrent mocks base method.
func (m *MockAPI) SetMinCurrent(arg0 float64) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetMinCurrent", arg0)
}
// SetMinCurrent indicates an expected call of SetMinCurrent.
func (mr *MockAPIMockRecorder) SetMinCurrent(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMinCurrent", reflect.TypeOf((*MockAPI)(nil).SetMinCurrent), arg0)
}
// SetMinSoc mocks base method.
func (m *MockAPI) SetMinSoc(arg0 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetMinSoc", arg0)
}
// SetMinSoc indicates an expected call of SetMinSoc.
func (mr *MockAPIMockRecorder) SetMinSoc(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMinSoc", reflect.TypeOf((*MockAPI)(nil).SetMinSoc), arg0)
}
// SetMode mocks base method.
func (m *MockAPI) SetMode(arg0 api.ChargeMode) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetMode", arg0)
}
// SetMode indicates an expected call of SetMode.
func (mr *MockAPIMockRecorder) SetMode(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetMode", reflect.TypeOf((*MockAPI)(nil).SetMode), arg0)
}
// SetPhases mocks base method.
func (m *MockAPI) SetPhases(arg0 int) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetPhases", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SetPhases indicates an expected call of SetPhases.
func (mr *MockAPIMockRecorder) SetPhases(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetPhases", reflect.TypeOf((*MockAPI)(nil).SetPhases), arg0)
}
// SetTargetEnergy mocks base method.
func (m *MockAPI) SetTargetEnergy(arg0 float64) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetTargetEnergy", arg0)
}
// SetTargetEnergy indicates an expected call of SetTargetEnergy.
func (mr *MockAPIMockRecorder) SetTargetEnergy(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTargetEnergy", reflect.TypeOf((*MockAPI)(nil).SetTargetEnergy), arg0)
}
// SetTargetSoc mocks base method.
func (m *MockAPI) SetTargetSoc(arg0 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetTargetSoc", arg0)
}
// SetTargetSoc indicates an expected call of SetTargetSoc.
func (mr *MockAPIMockRecorder) SetTargetSoc(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTargetSoc", reflect.TypeOf((*MockAPI)(nil).SetTargetSoc), arg0)
}
// SetTargetTime mocks base method.
func (m *MockAPI) SetTargetTime(arg0 time.Time) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "SetTargetTime", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// SetTargetTime indicates an expected call of SetTargetTime.
func (mr *MockAPIMockRecorder) SetTargetTime(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTargetTime", reflect.TypeOf((*MockAPI)(nil).SetTargetTime), arg0)
}
// SetVehicle mocks base method.
func (m *MockAPI) SetVehicle(arg0 api.Vehicle) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetVehicle", arg0)
}
// SetVehicle indicates an expected call of SetVehicle.
func (mr *MockAPIMockRecorder) SetVehicle(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetVehicle", reflect.TypeOf((*MockAPI)(nil).SetVehicle), arg0)
}
// StartVehicleDetection mocks base method.
func (m *MockAPI) StartVehicleDetection() {
m.ctrl.T.Helper()
m.ctrl.Call(m, "StartVehicleDetection")
}
// StartVehicleDetection indicates an expected call of StartVehicleDetection.
func (mr *MockAPIMockRecorder) StartVehicleDetection() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartVehicleDetection", reflect.TypeOf((*MockAPI)(nil).StartVehicleDetection))
}
// Title mocks base method.
func (m *MockAPI) Title() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Title")
ret0, _ := ret[0].(string)
return ret0
}
// Title indicates an expected call of Title.
func (mr *MockAPIMockRecorder) Title() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Title", reflect.TypeOf((*MockAPI)(nil).Title))
}

View file

@ -3,6 +3,7 @@ package core
import (
"errors"
"fmt"
"math"
"time"
"github.com/evcc-io/evcc/api"
@ -17,6 +18,11 @@ func (lp *Loadpoint) Title() string {
return lp.Title_
}
// Priority returns the loadpoint priority
func (lp *Loadpoint) Priority() int {
return lp.Priority_
}
// GetStatus returns the charging status
func (lp *Loadpoint) GetStatus() api.ChargeStatus {
lp.Lock()
@ -285,6 +291,22 @@ func (lp *Loadpoint) GetChargePower() float64 {
return lp.chargePower
}
// GetChargePowerFlexibility returns the flexible amount of current charging power
func (lp *Loadpoint) GetChargePowerFlexibility() float64 {
// no locking
mode := lp.GetMode()
if mode == api.ModeNow || !lp.charging() || lp.minSocNotReached() {
return 0
}
if mode == api.ModePV {
return lp.GetChargePower()
}
// MinPV mode
return math.Max(0, lp.GetChargePower()-lp.GetMinPower())
}
// GetMinCurrent returns the min loadpoint current
func (lp *Loadpoint) GetMinCurrent() float64 {
lp.Lock()

View file

@ -0,0 +1,34 @@
package prioritizer
import (
"github.com/evcc-io/evcc/core/loadpoint"
)
type Prioritizer struct {
demand map[loadpoint.API]float64
}
func New() *Prioritizer {
return &Prioritizer{
demand: make(map[loadpoint.API]float64),
}
}
func (p *Prioritizer) UpdateChargePowerFlexibility(lp loadpoint.API) {
if power := lp.GetChargePowerFlexibility(); power >= 0 {
p.demand[lp] = power
}
}
func (p *Prioritizer) GetChargePowerFlexibility(lp loadpoint.API) float64 {
prio := lp.Priority()
var reduceBy float64
for lp, power := range p.demand {
if lp.Priority() < prio {
reduceBy += power
}
}
return reduceBy
}

View file

@ -0,0 +1,36 @@
package prioritizer
import (
"testing"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
func TestPrioritzer(t *testing.T) {
ctrl := gomock.NewController(t)
p := New()
lo := loadpoint.NewMockAPI(ctrl)
lo.EXPECT().Priority().Return(0).AnyTimes()
hi := loadpoint.NewMockAPI(ctrl)
hi.EXPECT().Priority().Return(1).AnyTimes()
// no additional power available
lo.EXPECT().GetChargePowerFlexibility().Return(300.0)
p.UpdateChargePowerFlexibility(lo)
assert.Equal(t, 0.0, p.GetChargePowerFlexibility(lo))
// additional power available
hi.EXPECT().GetChargePowerFlexibility().Return(1e3)
p.UpdateChargePowerFlexibility(hi)
assert.Equal(t, 300.0, p.GetChargePowerFlexibility(hi))
// additional power removed
lo.EXPECT().GetChargePowerFlexibility().Return(0.0)
p.UpdateChargePowerFlexibility(lo)
assert.Equal(t, 0.0, p.GetChargePowerFlexibility(hi))
}

View file

@ -14,6 +14,7 @@ import (
"github.com/evcc-io/evcc/core/db"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/core/planner"
"github.com/evcc-io/evcc/core/prioritizer"
"github.com/evcc-io/evcc/push"
serverdb "github.com/evcc-io/evcc/server/db"
"github.com/evcc-io/evcc/tariff"
@ -25,6 +26,7 @@ const standbyPower = 10 // consider less than 10W as charger in standby
// Updater abstracts the Loadpoint implementation for testing
type Updater interface {
loadpoint.API
Update(availablePower float64, batteryBuffered bool)
}
@ -68,6 +70,7 @@ type Site struct {
tariffs tariff.Tariffs // Tariff
loadpoints []*Loadpoint // Loadpoints
coordinator *coordinator.Coordinator // Vehicles
prioritizer *prioritizer.Prioritizer // Power budgets
savings *Savings // Savings
// cached state
@ -108,6 +111,7 @@ func NewSiteFromConfig(
site.loadpoints = loadpoints
site.tariffs = tariffs
site.coordinator = coordinator.New(log, vehicles)
site.prioritizer = prioritizer.New()
site.savings = NewSavings(tariffs)
// upload telemetry on shutdown
@ -485,7 +489,7 @@ func (site *Site) updateMeters() error {
// sitePower returns the net power exported by the site minus a residual margin.
// negative values mean grid: export, battery: charging
func (site *Site) sitePower(totalChargePower float64) (float64, error) {
func (site *Site) sitePower(totalChargePower, flexiblePower float64) (float64, error) {
if err := site.updateMeters(); err != nil {
return 0, err
}
@ -537,6 +541,12 @@ func (site *Site) sitePower(totalChargePower float64) (float64, error) {
site.publish("auxPower", auxPower)
sitePower -= auxPower
// handle priority
if flexiblePower > 0 {
site.log.DEBUG.Printf("giving loadpoint priority for additional: %.0fW", flexiblePower)
sitePower -= flexiblePower
}
site.log.DEBUG.Printf("site power: %.0fW", sitePower)
return sitePower, nil
@ -609,9 +619,17 @@ func (site *Site) update(lp Updater) {
for _, lp := range site.loadpoints {
lp.UpdateChargePower()
totalChargePower += lp.GetChargePower()
site.prioritizer.UpdateChargePowerFlexibility(lp)
}
if sitePower, err := site.sitePower(totalChargePower); err == nil {
// prioritize if possible
var flexiblePower float64
if lp.GetMode() == api.ModePV {
flexiblePower = site.prioritizer.GetChargePowerFlexibility(lp)
}
if sitePower, err := site.sitePower(totalChargePower, flexiblePower); err == nil {
lp.Update(sitePower, site.batteryBuffered)
// ignore negative pvPower values as that means it is not an energy source but consumption