Site: respect minSoc in maxDischargePower calculation (#32664)
This commit is contained in:
parent
fdea008b0b
commit
9ef7ea748a
2 changed files with 71 additions and 2 deletions
14
core/site.go
14
core/site.go
|
|
@ -715,8 +715,18 @@ func (site *Site) updateBatteryMeters() {
|
|||
}
|
||||
|
||||
if bpl, ok := api.Cap[api.BatteryPowerLimiter](meter); ok && maxDischargePower >= 0 {
|
||||
_, discharge := bpl.GetPowerLimits()
|
||||
maxDischargePower += discharge
|
||||
var empty bool
|
||||
if bsl, ok := api.Cap[api.BatterySocLimiter](meter); ok {
|
||||
minSoc, _ := bsl.GetSocLimits()
|
||||
if mm[i].Soc != nil && *mm[i].Soc <= minSoc {
|
||||
empty = true
|
||||
}
|
||||
}
|
||||
|
||||
if !empty {
|
||||
_, discharge := bpl.GetPowerLimits()
|
||||
maxDischargePower += discharge
|
||||
}
|
||||
} else {
|
||||
maxDischargePower = -1 // any battery without a limit disables the cap
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ func (m *mockBatteryPowerLimiter) GetPowerLimits() (float64, float64) {
|
|||
return m.charge, m.discharge
|
||||
}
|
||||
|
||||
func (m *mockBatteryPowerLimiter) Soc() (float64, error) {
|
||||
return 50, nil
|
||||
}
|
||||
|
||||
type mockMeter struct {
|
||||
api.Meter
|
||||
}
|
||||
|
|
@ -26,6 +30,10 @@ func (m *mockMeter) CurrentPower() (float64, error) {
|
|||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockMeter) Soc() (float64, error) {
|
||||
return 50, nil
|
||||
}
|
||||
|
||||
func TestBatteryMaxDischargePowerAggregation(t *testing.T) {
|
||||
site := &Site{
|
||||
log: util.NewLogger("foo"),
|
||||
|
|
@ -53,3 +61,54 @@ func TestBatteryMaxDischargePowerAggregation(t *testing.T) {
|
|||
site.updateBatteryMeters()
|
||||
assert.Equal(t, 5000.0, site.GetBatteryMaxDischargePower())
|
||||
}
|
||||
|
||||
type mockBatterySocLimiter struct {
|
||||
api.Meter
|
||||
soc, min, max float64
|
||||
}
|
||||
|
||||
func (m *mockBatterySocLimiter) Soc() (float64, error) {
|
||||
return m.soc, nil
|
||||
}
|
||||
|
||||
func (m *mockBatterySocLimiter) GetSocLimits() (float64, float64) {
|
||||
return m.min, m.max
|
||||
}
|
||||
|
||||
type mockLimiter struct {
|
||||
mockBatterySocLimiter
|
||||
discharge float64
|
||||
}
|
||||
|
||||
func (m *mockLimiter) GetPowerLimits() (float64, float64) {
|
||||
return 0, m.discharge
|
||||
}
|
||||
|
||||
func TestBatteryMaxDischargePowerWithMinSoc(t *testing.T) {
|
||||
site := &Site{
|
||||
log: util.NewLogger("foo"),
|
||||
}
|
||||
|
||||
// one battery empty (soc <= min), one normal
|
||||
m1 := &mockLimiter{mockBatterySocLimiter: mockBatterySocLimiter{Meter: &mockMeter{}, soc: 10, min: 20}, discharge: 2000}
|
||||
m2 := &mockLimiter{mockBatterySocLimiter: mockBatterySocLimiter{Meter: &mockMeter{}, soc: 50, min: 20}, discharge: 3000}
|
||||
|
||||
site.batteryMeters = []config.Device[api.Meter]{
|
||||
config.NewStaticDevice[api.Meter](config.Named{Name: "bat1"}, m1),
|
||||
config.NewStaticDevice[api.Meter](config.Named{Name: "bat2"}, m2),
|
||||
}
|
||||
|
||||
site.updateBatteryMeters()
|
||||
// Only m2 should contribute
|
||||
assert.Equal(t, 3000.0, site.GetBatteryMaxDischargePower())
|
||||
|
||||
// Both empty
|
||||
m3 := &mockLimiter{mockBatterySocLimiter: mockBatterySocLimiter{Meter: &mockMeter{}, soc: 15, min: 20}, discharge: 3000}
|
||||
site.batteryMeters = []config.Device[api.Meter]{
|
||||
config.NewStaticDevice[api.Meter](config.Named{Name: "bat1"}, m1),
|
||||
config.NewStaticDevice[api.Meter](config.Named{Name: "bat3"}, m3),
|
||||
}
|
||||
|
||||
site.updateBatteryMeters()
|
||||
assert.Equal(t, 0.0, site.GetBatteryMaxDischargePower())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue