Add battery max charge/discharge power (#22944)
This commit is contained in:
parent
48175688b7
commit
7101f7049f
9 changed files with 3016 additions and 191 deletions
|
|
@ -49,6 +49,11 @@ type MaxACPowerGetter interface {
|
|||
MaxACPower() float64
|
||||
}
|
||||
|
||||
// BatteryMaxPowerGetter provides max AC charge- and discharge power in W
|
||||
type BatteryMaxPowerGetter interface {
|
||||
GetMaxChargeDischargePower() (float64, float64)
|
||||
}
|
||||
|
||||
// ChargeState provides current charging status
|
||||
type ChargeState interface {
|
||||
Status() (ChargeStatus, error)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ var a struct {
|
|||
api.BatteryCapacity
|
||||
api.BatteryController
|
||||
api.SocLimiter
|
||||
api.BatteryMaxPowerGetter
|
||||
}
|
||||
|
||||
func typ(i any) string {
|
||||
|
|
@ -59,7 +60,7 @@ var dependents = map[string][]string{
|
|||
typ(&a.Meter): {typ(&a.MeterEnergy), typ(&a.PhaseCurrents), typ(&a.PhaseVoltages), typ(&a.PhasePowers), typ(&a.MaxACPowerGetter)},
|
||||
typ(&a.PhaseCurrents): {typ(&a.PhasePowers)}, // phase powers are only used to determine currents sign
|
||||
typ(&a.PhaseSwitcher): {typ(&a.PhaseGetter)},
|
||||
typ(&a.Battery): {typ(&a.BatteryCapacity), typ(&a.BatteryController), typ(&a.SocLimiter)},
|
||||
typ(&a.Battery): {typ(&a.BatteryCapacity), typ(&a.BatteryController), typ(&a.SocLimiter), typ(&a.BatteryMaxPowerGetter)},
|
||||
}
|
||||
|
||||
// hasIntersection returns if the slices intersect
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
var (
|
||||
eta = float32(0.9) // efficiency of the battery charging/discharging
|
||||
batteryPower = float32(6000) // power of the battery in W
|
||||
batteryPower = float32(6000) // default power of the battery in W
|
||||
|
||||
updated time.Time
|
||||
)
|
||||
|
|
@ -183,20 +183,25 @@ func (site *Site) optimizerUpdate(battery []measurement) error {
|
|||
dev := site.batteryMeters[i]
|
||||
|
||||
bat := evopt.BatteryConfig{
|
||||
CMin: 0,
|
||||
CMax: batteryPower,
|
||||
DMax: batteryPower,
|
||||
SMin: 0,
|
||||
SMax: float32(*b.Capacity * 1e3), // Wh
|
||||
SInitial: float32(*b.Capacity * *b.Soc * 10), // Wh
|
||||
PA: pa,
|
||||
}
|
||||
|
||||
// TODO atm we cannot cannot control charge from grid speed
|
||||
if _, ok := (dev.Instance()).(api.BatteryController); ok {
|
||||
instance := dev.Instance()
|
||||
|
||||
if _, ok := instance.(api.BatteryController); ok {
|
||||
bat.ChargeFromGrid = lo.ToPtr(true)
|
||||
}
|
||||
|
||||
if m, ok := instance.(api.BatteryMaxPowerGetter); ok {
|
||||
min, max := m.GetMaxChargeDischargePower()
|
||||
bat.CMin = float32(min)
|
||||
bat.CMax = float32(max)
|
||||
}
|
||||
|
||||
req.Batteries = append(req.Batteries, bat)
|
||||
|
||||
details.BatteryDetails = append(details.BatteryDetails, batteryDetail{
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ func init() {
|
|||
registry.AddCtx(api.Custom, NewConfigurableFromConfig)
|
||||
}
|
||||
|
||||
//go:generate go tool decorate -f decorateMeter -b api.Meter -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.PhaseCurrents,Currents,func() (float64, float64, float64, error)" -t "api.PhaseVoltages,Voltages,func() (float64, float64, float64, error)" -t "api.PhasePowers,Powers,func() (float64, float64, float64, error)" -t "api.Battery,Soc,func() (float64, error)" -t "api.BatteryCapacity,Capacity,func() float64" -t "api.MaxACPowerGetter,MaxACPower,func() float64" -t "api.BatteryController,SetBatteryMode,func(api.BatteryMode) error"
|
||||
//go:generate go tool decorate -f decorateMeter -b api.Meter -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.PhaseCurrents,Currents,func() (float64, float64, float64, error)" -t "api.PhaseVoltages,Voltages,func() (float64, float64, float64, error)" -t "api.PhasePowers,Powers,func() (float64, float64, float64, error)" -t "api.Battery,Soc,func() (float64, error)" -t "api.BatteryCapacity,Capacity,func() float64" -t "api.BatteryMaxPowerGetter,GetMaxChargeDischargePower,func() (float64, float64)" -t "api.BatteryController,SetBatteryMode,func(api.BatteryMode) error" -t "api.MaxACPowerGetter,MaxACPower,func() float64"
|
||||
|
||||
// NewConfigurableFromConfig creates api.Meter from config
|
||||
func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}) (api.Meter, error) {
|
||||
|
|
@ -26,11 +26,12 @@ func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}
|
|||
pvMaxACPower `mapstructure:",squash"`
|
||||
|
||||
// battery
|
||||
batteryCapacity `mapstructure:",squash"`
|
||||
batterySocLimits `mapstructure:",squash"`
|
||||
Soc *plugin.Config // optional
|
||||
LimitSoc *plugin.Config // optional
|
||||
BatteryMode *plugin.Config // optional
|
||||
batteryCapacity `mapstructure:",squash"`
|
||||
batterySocLimits `mapstructure:",squash"`
|
||||
batteryChargeDischargePower `mapstructure:",squash"`
|
||||
Soc *plugin.Config // optional
|
||||
LimitSoc *plugin.Config // optional
|
||||
BatteryMode *plugin.Config // optional
|
||||
}{
|
||||
batterySocLimits: batterySocLimits{
|
||||
MinSoc: 20,
|
||||
|
|
@ -82,7 +83,11 @@ func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}
|
|||
}
|
||||
}
|
||||
|
||||
res := m.Decorate(energyG, currentsG, voltagesG, powersG, socG, cc.batteryCapacity.Decorator(), cc.pvMaxACPower.Decorator(), batModeS)
|
||||
res := m.Decorate(
|
||||
energyG, currentsG, voltagesG, powersG,
|
||||
socG, cc.batteryCapacity.Decorator(), cc.batteryChargeDischargePower.Decorator(), batModeS,
|
||||
cc.pvMaxACPower.Decorator(),
|
||||
)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
@ -106,10 +111,15 @@ func (m *Meter) Decorate(
|
|||
currents, voltages, powers func() (float64, float64, float64, error),
|
||||
batterySoc func() (float64, error),
|
||||
batteryCapacity func() float64,
|
||||
maxACPower func() float64,
|
||||
batteryChargeDischargePower func() (float64, float64),
|
||||
setBatteryMode func(api.BatteryMode) error,
|
||||
maxACPower func() float64,
|
||||
) api.Meter {
|
||||
return decorateMeter(m, totalEnergy, currents, voltages, powers, batterySoc, batteryCapacity, maxACPower, setBatteryMode)
|
||||
return decorateMeter(m,
|
||||
totalEnergy, currents, voltages, powers,
|
||||
batterySoc, batteryCapacity, batteryChargeDischargePower, setBatteryMode,
|
||||
maxACPower,
|
||||
)
|
||||
}
|
||||
|
||||
// CurrentPower implements the api.Meter interface
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func NewMovingAverageFromConfig(ctx context.Context, other map[string]interface{
|
|||
powers = m.Powers
|
||||
}
|
||||
|
||||
return meter.Decorate(totalEnergy, currents, voltages, powers, batterySoc, cc.Meter.batteryCapacity.Decorator(), nil, nil), nil
|
||||
return meter.Decorate(totalEnergy, currents, voltages, powers, batterySoc, cc.Meter.batteryCapacity.Decorator(), nil, nil, nil), nil
|
||||
}
|
||||
|
||||
type MovingAverage struct {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -139,7 +139,7 @@ func NewOpenWBFromConfig(other map[string]interface{}) (api.Meter, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
res := m.Decorate(nil, currents, nil, nil, soc, capacity, nil, nil)
|
||||
res := m.Decorate(nil, currents, nil, nil, soc, capacity, nil, nil, nil)
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,23 @@ func (m *batteryCapacity) Decorator() func() float64 {
|
|||
}
|
||||
}
|
||||
|
||||
type batteryChargeDischargePower struct {
|
||||
MaxChargePower float64
|
||||
MaxDischargePower float64
|
||||
}
|
||||
|
||||
// var _ api.BatteryMaxPowerGetter = (*batteryChargeDischargePower)(nil)
|
||||
|
||||
// Decorator returns the max charge/discharge power decorator
|
||||
func (m *batteryChargeDischargePower) Decorator() func() (float64, float64) {
|
||||
if m.MaxChargePower == 0 || m.MaxDischargePower == 0 {
|
||||
return nil
|
||||
}
|
||||
return func() (float64, float64) {
|
||||
return m.MaxChargePower, m.MaxDischargePower
|
||||
}
|
||||
}
|
||||
|
||||
type batterySocLimits struct {
|
||||
MinSoc, MaxSoc float64
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,11 +337,6 @@ params:
|
|||
en: For forced charging of the battery.
|
||||
de: Für erzwungenes Laden des Speichers.
|
||||
advanced: true
|
||||
- name: chargepower
|
||||
description:
|
||||
en: Maximum charge power
|
||||
de: Maximale Ladeleistung
|
||||
deprecated: true
|
||||
- name: maxchargerate
|
||||
unit: "%"
|
||||
type: int
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue