Skip to content

Commit

Permalink
Refactor ChargeRemainder into ChargeFinishTimer (evcc-io#352)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Sep 16, 2020
1 parent 0f73d5d commit c78a43b
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 28 deletions.
6 changes: 3 additions & 3 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ type Vehicle interface {
ChargeState() (float64, error)
}

// ChargeRemainder provides current charge cycle duration
type ChargeRemainder interface {
RemainingTime() (time.Duration, error)
// ChargeFinishTimer provides estimated charge cycle finish time
type ChargeFinishTimer interface {
FinishTime() (time.Time, error)
}
8 changes: 4 additions & 4 deletions cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ func dumpAPIs(v interface{}) {
}
}

if v, ok := v.(api.ChargeRemainder); ok {
if duration, err := v.RemainingTime(); err != nil {
fmt.Printf("Remaining: %v\n", err)
if v, ok := v.(api.ChargeFinishTimer); ok {
if time, err := v.FinishTime(); err != nil {
fmt.Printf("Finish time: %v\n", err)
} else {
fmt.Printf("Remaining: %v\n", duration)
fmt.Printf("Finish time: %v\n", time)
}
}

Expand Down
5 changes: 3 additions & 2 deletions core/wrapper/socestimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ func (s *SocEstimator) RemainingChargeDuration(chargePower float64, targetSoC in
}

// use vehicle api if available
if vr, ok := s.vehicle.(api.ChargeRemainder); ok {
timeRemaining, err := vr.RemainingTime()
if vr, ok := s.vehicle.(api.ChargeFinishTimer); ok {
finishTime, err := vr.FinishTime()
if err == nil {
timeRemaining := time.Until(finishTime)
return time.Duration(float64(timeRemaining) * percentRemaining / (100 - s.socCharge))
}

Expand Down
17 changes: 17 additions & 0 deletions provider/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,20 @@ func (c *Cached) DurationGetter() func() (time.Duration, error) {
return c.val.(time.Duration), c.err
}
}

// TimeGetter gets time.Time value
func (c *Cached) TimeGetter() func() (time.Time, error) {
g, ok := c.getter.(func() (time.Time, error))
if !ok {
c.log.FATAL.Fatalf("invalid type: %T", c.getter)
}

return func() (time.Time, error) {
if c.clock.Since(c.updated) > c.cache {
c.val, c.err = g()
c.updated = c.clock.Now()
}

return c.val.(time.Time), c.err
}
}
16 changes: 8 additions & 8 deletions vehicle/audi.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ type Audi struct {
brand, country string
tokens audiTokenResponse
chargeStateG func() (float64, error)
remainingTimeG func() (time.Duration, error)
finishTimeG func() (time.Time, error)
}

func init() {
Expand Down Expand Up @@ -105,7 +105,7 @@ func NewAudiFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v.chargeStateG = provider.NewCached(v.chargeState, cc.Cache).FloatGetter()
v.remainingTimeG = provider.NewCached(v.remainingTime, cc.Cache).DurationGetter()
v.finishTimeG = provider.NewCached(v.finishTime, cc.Cache).TimeGetter()

var err error
jar, err := cookiejar.New(&cookiejar.Options{
Expand Down Expand Up @@ -397,8 +397,8 @@ func (v *Audi) ChargeState() (float64, error) {
return v.chargeStateG()
}

// remainingTime implements the Vehicle.ChargeRemainder interface
func (v *Audi) remainingTime() (time.Duration, error) {
// finishTime implements the Vehicle.ChargeFinishTimer interface
func (v *Audi) finishTime() (time.Time, error) {
var res audiChargerResponse
uri := fmt.Sprintf("%s/bs/batterycharge/v1/%s/%s/vehicles/%s/charger", vwAPI, v.brand, v.country, v.vin)
err := v.getJSON(uri, &res)
Expand All @@ -408,10 +408,10 @@ func (v *Audi) remainingTime() (time.Duration, error) {
timestamp, err = time.Parse(time.RFC3339, res.Charger.Status.BatteryStatusData.RemainingChargingTime.Timestamp)
}

return time.Duration(res.Charger.Status.BatteryStatusData.RemainingChargingTime.Content)*time.Minute - time.Since(timestamp), err
return timestamp.Add(time.Duration(res.Charger.Status.BatteryStatusData.RemainingChargingTime.Content) * time.Minute), err
}

// RemainingTime implements the Vehicle.ChargeRemainder interface
func (v *Audi) RemainingTime() (time.Duration, error) {
return v.remainingTimeG()
// FinishTime implements the Vehicle.ChargeFinishTimer interface
func (v *Audi) FinishTime() (time.Time, error) {
return v.finishTimeG()
}
22 changes: 11 additions & 11 deletions vehicle/renault.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ type batteryAttributes struct {
PlugStatus int `json:"plugStatus"`
LastUpdateTime string `json:"lastUpdateTime"`
ChargePower int `json:"chargePower"`
RemainingTime *int `json:"chargingRemainingTime"`
FinishTime *int `json:"chargingFinishTime"`
}

// Renault is an api.Vehicle implementation for Renault cars
Expand All @@ -93,7 +93,7 @@ type Renault struct {
gigyaJwtToken string
accountID string
chargeStateG func() (float64, error)
remainingTimeG func() (time.Duration, error)
finishTimeG func() (time.Time, error)
}

func init() {
Expand Down Expand Up @@ -138,7 +138,7 @@ func NewRenaultFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}

v.chargeStateG = provider.NewCached(v.chargeState, cc.Cache).FloatGetter()
v.remainingTimeG = provider.NewCached(v.remainingTime, cc.Cache).DurationGetter()
v.finishTimeG = provider.NewCached(v.finishTime, cc.Cache).TimeGetter()

return v, nil
}
Expand Down Expand Up @@ -321,8 +321,8 @@ func (v *Renault) ChargeState() (float64, error) {
return v.chargeStateG()
}

// remainingTime implements the Vehicle.ChargeRemainder interface
func (v *Renault) remainingTime() (time.Duration, error) {
// finishTime implements the Vehicle.ChargeFinishTimer interface
func (v *Renault) finishTime() (time.Time, error) {
uri := fmt.Sprintf("%s/commerce/v1/accounts/%s/kamereon/kca/car-adapter/v2/cars/%s/battery-status", v.kamereon.Target, v.accountID, v.vin)
kr, err := v.kamereonRequest(uri)

Expand All @@ -338,14 +338,14 @@ func (v *Renault) remainingTime() (time.Duration, error) {
timestamp, err = time.Parse(time.RFC3339, kr.Data.Attributes.Timestamp)
}

if kr.Data.Attributes.RemainingTime == nil {
return 0, errors.New("estimate not available")
if kr.Data.Attributes.FinishTime == nil {
return time.Time{}, errors.New("estimate not available")
}

return time.Duration(*kr.Data.Attributes.RemainingTime)*time.Minute - time.Since(timestamp), err
return timestamp.Add(time.Duration(*kr.Data.Attributes.FinishTime) * time.Minute), err
}

// RemainingTime implements the Vehicle.ChargeRemainder interface
func (v *Renault) RemainingTime() (time.Duration, error) {
return v.remainingTimeG()
// FinishTime implements the Vehicle.ChargeFinishTimer interface
func (v *Renault) FinishTime() (time.Time, error) {
return v.finishTimeG()
}

0 comments on commit c78a43b

Please sign in to comment.