Retry pv meter reads on error (#12514)

This commit is contained in:
andig 2024-02-27 21:46:49 +01:00 • committed by GitHub
parent 80826f8d83
commit 6b1b8bf8ae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 23 additions and 22 deletions

View file

@ -1,6 +1,9 @@
package core
import (
"time"
"github.com/cenkalti/backoff/v4"
"github.com/evcc-io/evcc/util"
)
@ -12,6 +15,13 @@ var (
Voltage float64
)
// bo returns an exponential backoff for reading meter power quickly
func bo() *backoff.ExponentialBackOff {
bo := backoff.NewExponentialBackOff()
bo.MaxElapsedTime = time.Second
return bo
}
// powerToCurrent is a helper function to convert power to per-phase current
func powerToCurrent(power float64, phases int) float64 {
if Voltage == 0 {

View file

@ -400,9 +400,9 @@ func (site *Site) publishDelta(key string, val interface{}) {
}
// updatePvMeters updates pv meters. All measurements are optional.
func (site *Site) updatePvMeters() {
func (site *Site) updatePvMeters() error {
if len(site.pvMeters) == 0 {
return
return nil
}
var totalEnergy float64
@ -413,8 +413,7 @@ func (site *Site) updatePvMeters() {
for i, meter := range site.pvMeters {
// pv power
power, err := meter.CurrentPower()
power, err := backoff.RetryWithData(meter.CurrentPower, bo())
if err == nil {
// ignore negative values which represent self-consumption
site.pvPower += max(0, power)
@ -422,8 +421,8 @@ func (site *Site) updatePvMeters() {
site.log.WARN.Printf("pv %d power: %.0fW is negative - check configuration if sign is correct", i+1, power)
}
} else {
err = fmt.Errorf("pv %d power: %v", i+1, err)
site.log.ERROR.Println(err)
// power is required- return on error
return fmt.Errorf("pv %d power: %v", i+1, err)
}
// pv energy (production)
@ -447,6 +446,8 @@ func (site *Site) updatePvMeters() {
site.publish(keys.PvPower, site.pvPower)
site.publish(keys.PvEnergy, totalEnergy)
site.publish(keys.Pv, mm)
return nil
}
// updateBatteryMeters updates battery meters. Power is retried, other measurements are optional.
@ -455,9 +456,6 @@ func (site *Site) updateBatteryMeters() error {
return nil
}
bo := backoff.NewExponentialBackOff()
bo.MaxElapsedTime = time.Second
var totalCapacity, totalEnergy float64
site.batteryPower = 0
@ -466,9 +464,7 @@ func (site *Site) updateBatteryMeters() error {
mm := make([]batteryMeasurement, len(site.batteryMeters))
for i, meter := range site.batteryMeters {
bo.Reset()
power, err := backoff.RetryWithData(meter.CurrentPower, bo)
power, err := backoff.RetryWithData(meter.CurrentPower, bo())
if err == nil {
site.batteryPower += power
if len(site.batteryMeters) > 1 {
@ -549,10 +545,7 @@ func (site *Site) updateGridMeter() error {
return nil
}
bo := backoff.NewExponentialBackOff()
bo.MaxElapsedTime = time.Second
res, err := backoff.RetryWithData(site.gridMeter.CurrentPower, bo)
res, err := backoff.RetryWithData(site.gridMeter.CurrentPower, bo())
if err == nil {
site.gridPower = res
site.log.DEBUG.Printf("grid meter: %.0fW", res)
@ -601,15 +594,13 @@ func (site *Site) updateGridMeter() error {
// updateMeter updates and publishes single meter
func (site *Site) updateMeters() error {
// errors ignored
site.updatePvMeters()
// power errors returned
// TODO parallelize once modbus supports that
if err := site.updatePvMeters(); err != nil {
return err
}
if err := site.updateBatteryMeters(); err != nil {
return err
}
// power errors returned
return site.updateGridMeter()
}