Skip to content

Commit

Permalink
Daheimladen: reduce api requests by adding cache
Browse files Browse the repository at this point in the history
  • Loading branch information
andig committed Sep 3, 2022
1 parent c52e2be commit f388eee
Showing 1 changed file with 60 additions and 37 deletions.
97 changes: 60 additions & 37 deletions charger/daheimladen.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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() {
Expand All @@ -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{
Expand All @@ -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,
Expand Down Expand Up @@ -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),
Expand All @@ -136,55 +188,26 @@ 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
}

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
}

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
}

0 comments on commit f388eee

Please sign in to comment.