Skip to content

Commit

Permalink
Add charge planner (#5445)
Browse files Browse the repository at this point in the history
  • Loading branch information
andig authored Dec 23, 2022
1 parent 03d6d14 commit a9666b5
Show file tree
Hide file tree
Showing 23 changed files with 699 additions and 421 deletions.
16 changes: 12 additions & 4 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/fatih/structs"
)

//go:generate mockgen -package mock -destination ../mock/mock_api.go github.com/evcc-io/evcc/api Charger,ChargeState,PhaseSwitcher,Identifier,Meter,MeterEnergy,Vehicle,ChargeRater,Battery
//go:generate mockgen -package mock -destination ../mock/mock_api.go github.com/evcc-io/evcc/api Charger,ChargeState,PhaseSwitcher,Identifier,Meter,MeterEnergy,Vehicle,ChargeRater,Battery,Tariff

// ChargeMode is the charge operation mode. Valid values are off, now, minpv and pv
type ChargeMode string
Expand Down Expand Up @@ -218,10 +218,18 @@ type Resurrector interface {
WakeUp() error
}

// Tariff is the grid tariff
// Rate is a grid tariff rate
type Rate struct {
Start, End time.Time
Price float64
}

// Rates is a slice of (future) tariff rates
type Rates []Rate

// Tariff is a tariff capable of retrieving tariff rates
type Tariff interface {
IsCheap() (bool, error)
CurrentPrice() (float64, error) // EUR/kWh, CHF/kWh, ...
Rates() (Rates, error)
}

// AuthProvider is the ability to provide OAuth authentication through the ui
Expand Down
29 changes: 29 additions & 0 deletions api/impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package api

import (
"encoding"
"errors"
"fmt"
"strings"
"time"
)

// ChargeModeString converts string to ChargeMode
Expand Down Expand Up @@ -36,3 +38,30 @@ func (c *ChargeMode) UnmarshalText(text []byte) error {

return nil
}

// Current returns the rates current rate or error
func (r Rates) Current(now time.Time) (Rate, error) {
for _, rr := range r {
if (rr.Start.Before(now) || rr.Start.Equal(now)) && rr.End.After(now) {
return rr, nil
}
}

return Rate{}, errors.New("no matching rate")
}

// implement sort.Interface
func (r Rates) Len() int {
return len(r)
}

func (r Rates) Less(i, j int) bool {
if r[i].Price == r[j].Price {
return r[i].Start.After(r[j].Start)
}
return r[i].Price < r[j].Price
}

func (r Rates) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}
28 changes: 28 additions & 0 deletions api/impl_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package api

import (
"sort"
"testing"
"time"

"github.com/benbjohnson/clock"
"github.com/stretchr/testify/assert"
)

func TestRatesSort(t *testing.T) {
clock := clock.NewMock()

r := Rates{
{
Price: 1,
Start: clock.Now(),
},
{
Price: 1,
Start: clock.Now().Add(time.Hour),
},
}

sort.Sort(r)
assert.Equal(t, clock.Now(), r[1].Start)
}
6 changes: 6 additions & 0 deletions core/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,11 @@ const (

vehicleRange = "vehicleRange" // vehicle range
vehicleOdometer = "vehicleOdometer" // vehicle odometer
vehicleSoc = "vehicleSoc" // vehicle soc
vehicleTargetSoc = "vehicleTargetSoc" // vehicle soc limit

minSoc = "minSoc" // min soc goal
targetSoc = "targetSoc" // target charging soc goal
targetTime = "targetTime" // target charging finish time goal
targetTimeActive = "targetTimeActive" // target charging plan has determined current slot to be an active slot
)
Loading

0 comments on commit a9666b5

Please sign in to comment.