From f388eeeebd7a11f382dddef691e3bfd9cf7c389f Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 3 Sep 2022 15:27:14 +0200 Subject: [PATCH] Daheimladen: reduce api requests by adding cache --- charger/daheimladen.go | 97 ++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/charger/daheimladen.go b/charger/daheimladen.go index 6acf248256..0e16e2b19c 100644 --- a/charger/daheimladen.go +++ b/charger/daheimladen.go @@ -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 }