Daheimladen: reduce api requests by adding cache

This commit is contained in:
andig 2022-09-03 15:27:14 +02:00
parent c52e2be1c2
commit f388eeeebd

View file

@ -4,9 +4,11 @@ import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/charger/daheimladen"
"github.com/evcc-io/evcc/provider"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"golang.org/x/oauth2"
@ -20,6 +22,9 @@ type DaheimLaden struct {
idTag string
token string
transactionID int32
statusG func() (daheimladen.GetLatestStatus, error)
meterG func() (daheimladen.GetLatestMeterValueResponse, error)
cache time.Duration
}
func init() {
@ -28,26 +33,30 @@ func init() {
// NewDaheimLadenFromConfig creates a DaheimLaden charger from generic config
func NewDaheimLadenFromConfig(other map[string]interface{}) (api.Charger, error) {
var cc struct {
cc := struct {
Token string
StationID string
Cache time.Duration
}{
Cache: time.Second,
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
return NewDaheimLaden(cc.Token, cc.StationID)
return NewDaheimLaden(cc.Token, cc.StationID, cc.Cache)
}
// NewDaheimLaden creates DaheimLaden charger
func NewDaheimLaden(token, stationID string) (*DaheimLaden, error) {
func NewDaheimLaden(token, stationID string, cache time.Duration) (*DaheimLaden, error) {
c := &DaheimLaden{
Helper: request.NewHelper(util.NewLogger("daheim")),
stationID: stationID,
connectorID: 1,
idTag: daheimladen.EVCC_IDTAG,
token: token,
cache: cache,
}
c.Client.Transport = &oauth2.Transport{
@ -57,18 +66,59 @@ func NewDaheimLaden(token, stationID string) (*DaheimLaden, error) {
}),
Base: c.Client.Transport,
}
c.reset()
return c, nil
}
// reset cache
func (c *DaheimLaden) reset() {
c.statusG = provider.Cached(func() (daheimladen.GetLatestStatus, error) {
var res daheimladen.GetLatestStatus
err := c.GetJSON(fmt.Sprintf("%s/cs/%s/status", daheimladen.BASE_URL, c.stationID), &res)
return res, err
}, c.cache)
c.meterG = provider.Cached(func() (daheimladen.GetLatestMeterValueResponse, error) {
var res daheimladen.GetLatestMeterValueResponse
err := c.GetJSON(fmt.Sprintf("%s/cs/%s/metervalue", daheimladen.BASE_URL, c.stationID), &res)
return res, err
}, c.cache)
}
// Status implements the api.Charger interface
func (c *DaheimLaden) Status() (api.ChargeStatus, error) {
res, err := c.statusG()
if err != nil {
return api.StatusNone, err
}
status := daheimladen.ChargePointStatus(res.Status)
switch status {
case daheimladen.AVAILABLE:
return api.StatusA, nil
case daheimladen.PREPARING:
return api.StatusB, nil
case daheimladen.CHARGING, daheimladen.FINISHING:
return api.StatusC, nil
case daheimladen.FAULTED:
return api.StatusF, nil
default:
return api.StatusNone, fmt.Errorf("invalid status: %s", res.Status)
}
}
// Enabled implements the api.Charger interface
func (c *DaheimLaden) Enabled() (bool, error) {
var res daheimladen.GetLatestStatus
err := c.GetJSON(fmt.Sprintf("%s/cs/%s/status", daheimladen.BASE_URL, c.stationID), &res)
res, err := c.statusG()
return res.Status == string(daheimladen.CHARGING), err
}
// Enable implements the api.Charger interface
func (c *DaheimLaden) Enable(enable bool) error {
defer c.reset()
if enable {
data := daheimladen.RemoteStartRequest{
ConnectorID: c.connectorID,
@ -117,6 +167,8 @@ func (c *DaheimLaden) Enable(enable bool) error {
// MaxCurrent implements the api.Charger interface
func (c *DaheimLaden) MaxCurrent(current int64) error {
defer c.reset()
data := daheimladen.ChangeConfigurationRequest{
Key: string(daheimladen.CHARGE_RATE),
Value: strconv.FormatInt(current, 10),
@ -136,36 +188,11 @@ func (c *DaheimLaden) MaxCurrent(current int64) error {
return err
}
// Status implements the api.Charger interface
func (c *DaheimLaden) Status() (api.ChargeStatus, error) {
var res daheimladen.GetLatestStatus
uri := fmt.Sprintf("%s/cs/%s/status", daheimladen.BASE_URL, c.stationID)
if err := c.GetJSON(uri, &res); err != nil {
return api.StatusNone, err
}
status := daheimladen.ChargePointStatus(res.Status)
switch status {
case daheimladen.AVAILABLE:
return api.StatusA, nil
case daheimladen.PREPARING:
return api.StatusB, nil
case daheimladen.CHARGING, daheimladen.FINISHING:
return api.StatusC, nil
case daheimladen.FAULTED:
return api.StatusF, nil
default:
return api.StatusNone, fmt.Errorf("invalid status: %s", res.Status)
}
}
var _ api.Meter = (*DaheimLaden)(nil)
// CurrentPower implements the api.Meter interface
func (c *DaheimLaden) CurrentPower() (float64, error) {
var res daheimladen.GetLatestMeterValueResponse
uri := fmt.Sprintf("%s/cs/%s/metervalue", daheimladen.BASE_URL, c.stationID)
err := c.GetJSON(uri, &res)
res, err := c.meterG()
return float64(res.ActivePowerImport * 1e3), err
}
@ -173,9 +200,7 @@ var _ api.MeterEnergy = (*DaheimLaden)(nil)
// TotalEnergy implements the api.MeterMeterEnergy interface
func (c *DaheimLaden) TotalEnergy() (float64, error) {
var res daheimladen.GetLatestMeterValueResponse
uri := fmt.Sprintf("%s/cs/%s/metervalue", daheimladen.BASE_URL, c.stationID)
err := c.GetJSON(uri, &res)
res, err := c.meterG()
return float64(res.EnergyActiveImportRegister), err
}
@ -183,8 +208,6 @@ var _ api.MeterCurrent = (*DaheimLaden)(nil)
// Currents implements the api.MeterCurrent interface
func (c *DaheimLaden) Currents() (float64, float64, float64, error) {
var res daheimladen.GetLatestMeterValueResponse
uri := fmt.Sprintf("%s/cs/%s/metervalue", daheimladen.BASE_URL, c.stationID)
err := c.GetJSON(uri, &res)
res, err := c.meterG()
return float64(res.CurrentImportPhaseL1), float64(res.CurrentImportPhaseL2), float64(res.CurrentImportPhaseL3), err
}