169 lines
4.7 KiB
Go
169 lines
4.7 KiB
Go
package vehicle
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/evcc-io/evcc/api"
|
|
"github.com/evcc-io/evcc/provider"
|
|
"github.com/evcc-io/evcc/util"
|
|
)
|
|
|
|
//go:generate go run ../cmd/tools/decorate.go -f decorateVehicle -b api.Vehicle -t "api.SocLimiter,GetLimitSoc,func() (int64, error)" -t "api.ChargeState,Status,func() (api.ChargeStatus, error)" -t "api.VehicleRange,Range,func() (int64, error)" -t "api.VehicleOdometer,Odometer,func() (float64, error)" -t "api.VehicleClimater,Climater,func() (bool, error)" -t "api.CurrentController,MaxCurrent,func(int64) error" -t "api.CurrentGetter,GetMaxCurrent,func() (float64, error)" -t "api.VehicleFinishTimer,FinishTime,func() (time.Time, error)" -t "api.Resurrector,WakeUp,func() error" -t "api.ChargeController,ChargeEnable,func(bool) error"
|
|
|
|
// Vehicle is an api.Vehicle implementation with configurable getters and setters.
|
|
type Vehicle struct {
|
|
*embed
|
|
socG func() (float64, error)
|
|
}
|
|
|
|
func init() {
|
|
registry.AddCtx(api.Custom, NewConfigurableFromConfig)
|
|
}
|
|
|
|
// NewConfigurableFromConfig creates a new Vehicle
|
|
func NewConfigurableFromConfig(ctx context.Context, other map[string]interface{}) (api.Vehicle, error) {
|
|
var cc struct {
|
|
embed `mapstructure:",squash"`
|
|
Soc provider.Config
|
|
LimitSoc *provider.Config
|
|
Status *provider.Config
|
|
Range *provider.Config
|
|
Odometer *provider.Config
|
|
Climater *provider.Config
|
|
MaxCurrent *provider.Config
|
|
GetMaxCurrent *provider.Config
|
|
FinishTime *provider.Config
|
|
Wakeup *provider.Config
|
|
ChargeEnable *provider.Config
|
|
}
|
|
|
|
if err := util.DecodeOther(other, &cc); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
socG, err := provider.NewFloatGetterFromConfig(ctx, cc.Soc)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("soc: %w", err)
|
|
}
|
|
|
|
v := &Vehicle{
|
|
embed: &cc.embed,
|
|
socG: socG,
|
|
}
|
|
|
|
// decorate range
|
|
var limitSoc func() (int64, error)
|
|
if cc.LimitSoc != nil {
|
|
limitSoc, err = provider.NewIntGetterFromConfig(ctx, *cc.LimitSoc)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("limitSoc: %w", err)
|
|
}
|
|
}
|
|
|
|
// decorate status
|
|
var status func() (api.ChargeStatus, error)
|
|
if cc.Status != nil {
|
|
get, err := provider.NewStringGetterFromConfig(ctx, *cc.Status)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("status: %w", err)
|
|
}
|
|
status = func() (api.ChargeStatus, error) {
|
|
s, err := get()
|
|
if err != nil {
|
|
return api.StatusNone, err
|
|
}
|
|
return api.ChargeStatusString(s)
|
|
}
|
|
}
|
|
|
|
// decorate range
|
|
var rng func() (int64, error)
|
|
if cc.Range != nil {
|
|
rng, err = provider.NewIntGetterFromConfig(ctx, *cc.Range)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("range: %w", err)
|
|
}
|
|
}
|
|
|
|
// decorate odometer
|
|
var odo func() (float64, error)
|
|
if cc.Odometer != nil {
|
|
odo, err = provider.NewFloatGetterFromConfig(ctx, *cc.Odometer)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("odometer: %w", err)
|
|
}
|
|
}
|
|
|
|
// decorate climater
|
|
var climater func() (bool, error)
|
|
if cc.Climater != nil {
|
|
climater, err = provider.NewBoolGetterFromConfig(ctx, *cc.Climater)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("climater: %w", err)
|
|
}
|
|
}
|
|
|
|
// decorate maxCurrent
|
|
var maxCurrent func(int64) error
|
|
if cc.MaxCurrent != nil {
|
|
maxCurrent, err = provider.NewIntSetterFromConfig(ctx, "maxcurrent", *cc.MaxCurrent)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("maxCurrent: %w", err)
|
|
}
|
|
}
|
|
|
|
// decorate getMaxCurrent
|
|
var getMaxCurrent func() (float64, error)
|
|
if cc.GetMaxCurrent != nil {
|
|
getMaxCurrent, err = provider.NewFloatGetterFromConfig(ctx, *cc.GetMaxCurrent)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getMaxCurrent: %w", err)
|
|
}
|
|
}
|
|
|
|
// decorate finishtime
|
|
var finishTime func() (time.Time, error)
|
|
if cc.FinishTime != nil {
|
|
stringG, err := provider.NewStringGetterFromConfig(ctx, *cc.FinishTime)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("finishTime: %w", err)
|
|
}
|
|
finishTime = func() (time.Time, error) {
|
|
s, err := stringG()
|
|
if err != nil {
|
|
return time.Time{}, err
|
|
}
|
|
return time.Parse(time.RFC3339, s)
|
|
}
|
|
}
|
|
|
|
// decorate wakeup
|
|
var wakeup func() error
|
|
if cc.Wakeup != nil {
|
|
set, err := provider.NewBoolSetterFromConfig(ctx, "wakeup", *cc.Wakeup)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("wakeup: %w", err)
|
|
}
|
|
wakeup = func() error {
|
|
return set(true)
|
|
}
|
|
}
|
|
|
|
// decorate chargeEnable
|
|
var chargeEnable func(bool) error
|
|
if cc.ChargeEnable != nil {
|
|
chargeEnable, err = provider.NewBoolSetterFromConfig(ctx, "chargeenable", *cc.ChargeEnable)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("chargeEnable: %w", err)
|
|
}
|
|
}
|
|
|
|
return decorateVehicle(v, limitSoc, status, rng, odo, climater, maxCurrent, getMaxCurrent, finishTime, wakeup, chargeEnable), nil
|
|
}
|
|
|
|
// Soc implements the api.Vehicle interface
|
|
func (v *Vehicle) Soc() (float64, error) {
|
|
return v.socG()
|
|
}
|