RCT: add retry (#9231)
This commit is contained in:
parent
d12ff40179
commit
06c17c33ae
3 changed files with 45 additions and 21 deletions
2
go.mod
2
go.mod
|
|
@ -66,7 +66,7 @@ require (
|
|||
github.com/mergermarket/go-pkcs7 v0.0.0-20170926155232-153b18ea13c9
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/mlnoga/rct v0.1.2-0.20230227143934-71af1fb7dfa1
|
||||
github.com/mlnoga/rct v0.1.2-0.20230731074838-03eacb926f99
|
||||
github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1
|
||||
github.com/mxschmitt/golang-combinations v1.1.0
|
||||
github.com/nicksnyder/go-i18n/v2 v2.2.1
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -822,8 +822,8 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
|
|||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mlnoga/rct v0.1.2-0.20230227143934-71af1fb7dfa1 h1:+OVWP3tJu+en06qieaXY/pcX+1qKp4X1oX9g3hMgOCk=
|
||||
github.com/mlnoga/rct v0.1.2-0.20230227143934-71af1fb7dfa1/go.mod h1:0lfd2mmBnBzIvuzYtdhG+2371u+cUfIxsYErm4P9KRI=
|
||||
github.com/mlnoga/rct v0.1.2-0.20230731074838-03eacb926f99 h1:sX4VwA7zgImnMqRgEkzP+3oKCgUHRF0OvHghFJ0pntY=
|
||||
github.com/mlnoga/rct v0.1.2-0.20230731074838-03eacb926f99/go.mod h1:0lfd2mmBnBzIvuzYtdhG+2371u+cUfIxsYErm4P9KRI=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
|
|||
60
meter/rct.go
60
meter/rct.go
|
|
@ -6,6 +6,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/util"
|
||||
|
||||
|
|
@ -42,6 +43,7 @@ meters:
|
|||
|
||||
// RCT implements the api.Meter interface
|
||||
type RCT struct {
|
||||
bo *backoff.ExponentialBackOff
|
||||
conn *rct.Connection // connection with the RCT device
|
||||
usage string // grid, pv, battery
|
||||
}
|
||||
|
|
@ -80,9 +82,14 @@ func NewRCT(uri, usage string, cache time.Duration, capacity func() float64) (ap
|
|||
return nil, err
|
||||
}
|
||||
|
||||
bo := backoff.NewExponentialBackOff()
|
||||
bo.MaxElapsedTime = time.Second
|
||||
bo.InitialInterval = 10 * time.Millisecond
|
||||
|
||||
m := &RCT{
|
||||
usage: strings.ToLower(usage),
|
||||
conn: conn,
|
||||
bo: bo,
|
||||
}
|
||||
|
||||
// decorate api.MeterEnergy
|
||||
|
|
@ -104,24 +111,24 @@ func NewRCT(uri, usage string, cache time.Duration, capacity func() float64) (ap
|
|||
func (m *RCT) CurrentPower() (float64, error) {
|
||||
switch m.usage {
|
||||
case "grid":
|
||||
res, err := m.conn.QueryFloat32(rct.TotalGridPowerW)
|
||||
return float64(res), err
|
||||
res, err := m.queryFloat(rct.TotalGridPowerW)
|
||||
return res, err
|
||||
|
||||
case "pv":
|
||||
a, err := m.conn.QueryFloat32(rct.SolarGenAPowerW)
|
||||
a, err := m.queryFloat(rct.SolarGenAPowerW)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
b, err := m.conn.QueryFloat32(rct.SolarGenBPowerW)
|
||||
b, err := m.queryFloat(rct.SolarGenBPowerW)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
c, err := m.conn.QueryFloat32(rct.S0ExternalPowerW)
|
||||
return float64(a + b + c), err
|
||||
c, err := m.queryFloat(rct.S0ExternalPowerW)
|
||||
return a + b + c, err
|
||||
|
||||
case "battery":
|
||||
res, err := m.conn.QueryFloat32(rct.BatteryPowerW)
|
||||
return float64(res), err
|
||||
res, err := m.queryFloat(rct.BatteryPowerW)
|
||||
return res, err
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid usage: %s", m.usage)
|
||||
|
|
@ -132,24 +139,24 @@ func (m *RCT) CurrentPower() (float64, error) {
|
|||
func (m *RCT) totalEnergy() (float64, error) {
|
||||
switch m.usage {
|
||||
case "grid":
|
||||
res, err := m.conn.QueryFloat32(rct.TotalEnergyGridWh)
|
||||
return float64(res / 1000), err
|
||||
res, err := m.queryFloat(rct.TotalEnergyGridWh)
|
||||
return res / 1000, err
|
||||
|
||||
case "pv":
|
||||
a, err := m.conn.QueryFloat32(rct.TotalEnergySolarGenAWh)
|
||||
a, err := m.queryFloat(rct.TotalEnergySolarGenAWh)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
b, err := m.conn.QueryFloat32(rct.TotalEnergySolarGenBWh)
|
||||
return float64((a + b) / 1000), err
|
||||
b, err := m.queryFloat(rct.TotalEnergySolarGenBWh)
|
||||
return (a + b) / 1000, err
|
||||
|
||||
case "battery":
|
||||
in, err := m.conn.QueryFloat32(rct.TotalEnergyBattInWh)
|
||||
in, err := m.queryFloat(rct.TotalEnergyBattInWh)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
out, err := m.conn.QueryFloat32(rct.TotalEnergyBattOutWh)
|
||||
return float64((in - out) / 1000), err
|
||||
out, err := m.queryFloat(rct.TotalEnergyBattOutWh)
|
||||
return (in - out) / 1000, err
|
||||
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid usage: %s", m.usage)
|
||||
|
|
@ -158,6 +165,23 @@ func (m *RCT) totalEnergy() (float64, error) {
|
|||
|
||||
// batterySoc implements the api.Battery interface
|
||||
func (m *RCT) batterySoc() (float64, error) {
|
||||
res, err := m.conn.QueryFloat32(rct.BatterySoC)
|
||||
return float64(res * 100), err
|
||||
res, err := m.queryFloat(rct.BatterySoC)
|
||||
return res * 100, err
|
||||
}
|
||||
|
||||
// queryFloat adds retry logic of recoverable errors to QueryFloat32
|
||||
func (m *RCT) queryFloat(id rct.Identifier) (float64, error) {
|
||||
started := time.Now()
|
||||
m.bo.Reset()
|
||||
|
||||
for {
|
||||
next := m.bo.NextBackOff()
|
||||
|
||||
res, err := m.conn.QueryFloat32(id)
|
||||
if err == nil || !errors.Is(err, &rct.RecoverableError{}) || time.Since(started)+next > m.bo.MaxElapsedTime {
|
||||
return float64(res), err
|
||||
}
|
||||
|
||||
time.Sleep(next)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue