diff --git a/vehicle/tronity.go b/vehicle/tronity.go index 9cfd01467..b9b671312 100644 --- a/vehicle/tronity.go +++ b/vehicle/tronity.go @@ -32,6 +32,7 @@ import ( "github.com/evcc-io/evcc/util/request" "github.com/evcc-io/evcc/util/sponsor" "github.com/evcc-io/evcc/vehicle/tronity" + "github.com/thoas/go-funk" "golang.org/x/oauth2" ) @@ -49,6 +50,8 @@ func init() { registry.Add("tronity", NewTronityFromConfig) } +//go:generate go run ../cmd/tools/decorate.go -f decorateTronity -b *Tronity -r api.Vehicle -t "api.ChargeState,Status,func() (api.ChargeStatus, error)" -t "api.VehicleOdometer,Odometer,func() (float64, error)" -t "api.VehicleStartCharge,StartCharge,func() error" -t "api.VehicleStopCharge,StopCharge,func() error" + // NewTronityFromConfig creates a new vehicle func NewTronityFromConfig(other map[string]interface{}) (api.Vehicle, error) { cc := struct { @@ -115,23 +118,41 @@ func NewTronityFromConfig(other map[string]interface{}) (api.Vehicle, error) { return nil, err } + var vehicle tronity.Vehicle if cc.VIN == "" && len(vehicles) == 1 { - v.vid = vehicles[0].ID + vehicle = vehicles[0] } else { - for _, vehicle := range vehicles { - if vehicle.VIN == strings.ToUpper(cc.VIN) { - v.vid = vehicle.ID + for _, v := range vehicles { + if v.VIN == strings.ToUpper(cc.VIN) { + vehicle = v } } } - if v.vid == "" { + if vehicle.ID == "" { return nil, errors.New("vin not found") } + v.vid = vehicle.ID v.bulkG = provider.NewCached(v.bulk, cc.Cache).InterfaceGetter() - return v, nil + var status func() (api.ChargeStatus, error) + if funk.ContainsString(vehicle.Scopes, tronity.ReadCharge) { + status = v.status + } + + var odometer func() (float64, error) + if funk.ContainsString(vehicle.Scopes, tronity.ReadOdometer) { + odometer = v.odometer + } + + var start, stop func() error + if funk.ContainsString(vehicle.Scopes, tronity.WriteChargeStartStop) { + start = v.startCharge + stop = v.stopCharge + } + + return decorateTronity(v, status, odometer, start, stop), nil } // RefreshToken performs token refresh by logging in with app context @@ -188,10 +209,8 @@ func (v *Tronity) SoC() (float64, error) { return 0, err } -var _ api.ChargeState = (*Tronity)(nil) - -// Status implements the api.ChargeState interface -func (v *Tronity) Status() (api.ChargeStatus, error) { +// status implements the api.ChargeState interface +func (v *Tronity) status() (api.ChargeStatus, error) { status := api.StatusA // disconnected res, err := v.bulkG() @@ -217,10 +236,8 @@ func (v *Tronity) Range() (int64, error) { return 0, err } -var _ api.VehicleOdometer = (*Tronity)(nil) - -// Odometer implements the api.VehicleOdometer interface -func (v *Tronity) Odometer() (float64, error) { +// odometer implements the api.VehicleOdometer interface +func (v *Tronity) odometer() (float64, error) { res, err := v.bulkG() if res, ok := res.(tronity.Bulk); err == nil && ok { @@ -246,18 +263,14 @@ func (v *Tronity) post(uri string) error { return err } -var _ api.VehicleStartCharge = (*Tronity)(nil) - -// StartCharge implements the api.VehicleStartCharge interface -func (v *Tronity) StartCharge() error { +// startCharge implements the api.VehicleStartCharge interface +func (v *Tronity) startCharge() error { uri := fmt.Sprintf("%s/v1/vehicles/%s/charge_start", tronity.URI, v.vid) return v.post(uri) } -var _ api.VehicleStopCharge = (*Tronity)(nil) - -// StopCharge implements the api.VehicleStopCharge interface -func (v *Tronity) StopCharge() error { +// stopCharge implements the api.VehicleStopCharge interface +func (v *Tronity) stopCharge() error { uri := fmt.Sprintf("%s/v1/vehicles/%s/charge_stop", tronity.URI, v.vid) return v.post(uri) } diff --git a/vehicle/tronity/types.go b/vehicle/tronity/types.go index d4cb50b26..3bb20924c 100644 --- a/vehicle/tronity/types.go +++ b/vehicle/tronity/types.go @@ -2,6 +2,17 @@ package tronity // https://app.platform.tronity.io/docs#operation +const ( + ReadBattery = "read_battery" // Read EV battery's capacity and state of charge + ReadCharge = "read_charge" // Know whether vehicle is charging + ReadLocation = "read_location" // Access location + ReadOdometer = "read_odometer" // Retrieve total distance traveled + ReadVehicleInfo = "read_vehicle_info" // Know make, model, and year + ReadVIN = "read_vin" // Read VIN + WriteChargeStartStop = "write_charge_start_stop" // Start or stop your vehicle's charging + WriteWakeUp = "write_wake_up" // Wake up car. Only valid for Tesla +) + type Vehicles struct { Data []Vehicle } @@ -11,6 +22,7 @@ type Vehicle struct { VIN string DisplayName string Manufacture string + Scopes []string } type Bulk struct { diff --git a/vehicle/tronity_decorators.go b/vehicle/tronity_decorators.go new file mode 100644 index 000000000..b14005335 --- /dev/null +++ b/vehicle/tronity_decorators.go @@ -0,0 +1,281 @@ +package vehicle + +// Code generated by github.com/evcc-io/evcc/cmd/tools/decorate.go. DO NOT EDIT. + +import ( + "github.com/evcc-io/evcc/api" +) + +func decorateTronity(base *Tronity, chargeState func() (api.ChargeStatus, error), vehicleOdometer func() (float64, error), vehicleStartCharge func() error, vehicleStopCharge func() error) api.Vehicle { + switch { + case chargeState == nil && vehicleOdometer == nil && vehicleStartCharge == nil && vehicleStopCharge == nil: + return base + + case chargeState != nil && vehicleOdometer == nil && vehicleStartCharge == nil && vehicleStopCharge == nil: + return &struct { + *Tronity + api.ChargeState + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + } + + case chargeState == nil && vehicleOdometer != nil && vehicleStartCharge == nil && vehicleStopCharge == nil: + return &struct { + *Tronity + api.VehicleOdometer + }{ + Tronity: base, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + } + + case chargeState != nil && vehicleOdometer != nil && vehicleStartCharge == nil && vehicleStopCharge == nil: + return &struct { + *Tronity + api.ChargeState + api.VehicleOdometer + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + } + + case chargeState == nil && vehicleOdometer == nil && vehicleStartCharge != nil && vehicleStopCharge == nil: + return &struct { + *Tronity + api.VehicleStartCharge + }{ + Tronity: base, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + } + + case chargeState != nil && vehicleOdometer == nil && vehicleStartCharge != nil && vehicleStopCharge == nil: + return &struct { + *Tronity + api.ChargeState + api.VehicleStartCharge + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + } + + case chargeState == nil && vehicleOdometer != nil && vehicleStartCharge != nil && vehicleStopCharge == nil: + return &struct { + *Tronity + api.VehicleOdometer + api.VehicleStartCharge + }{ + Tronity: base, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + } + + case chargeState != nil && vehicleOdometer != nil && vehicleStartCharge != nil && vehicleStopCharge == nil: + return &struct { + *Tronity + api.ChargeState + api.VehicleOdometer + api.VehicleStartCharge + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + } + + case chargeState == nil && vehicleOdometer == nil && vehicleStartCharge == nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.VehicleStopCharge + }{ + Tronity: base, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + + case chargeState != nil && vehicleOdometer == nil && vehicleStartCharge == nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.ChargeState + api.VehicleStopCharge + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + + case chargeState == nil && vehicleOdometer != nil && vehicleStartCharge == nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.VehicleOdometer + api.VehicleStopCharge + }{ + Tronity: base, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + + case chargeState != nil && vehicleOdometer != nil && vehicleStartCharge == nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.ChargeState + api.VehicleOdometer + api.VehicleStopCharge + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + + case chargeState == nil && vehicleOdometer == nil && vehicleStartCharge != nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.VehicleStartCharge + api.VehicleStopCharge + }{ + Tronity: base, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + + case chargeState != nil && vehicleOdometer == nil && vehicleStartCharge != nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.ChargeState + api.VehicleStartCharge + api.VehicleStopCharge + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + + case chargeState == nil && vehicleOdometer != nil && vehicleStartCharge != nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.VehicleOdometer + api.VehicleStartCharge + api.VehicleStopCharge + }{ + Tronity: base, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + + case chargeState != nil && vehicleOdometer != nil && vehicleStartCharge != nil && vehicleStopCharge != nil: + return &struct { + *Tronity + api.ChargeState + api.VehicleOdometer + api.VehicleStartCharge + api.VehicleStopCharge + }{ + Tronity: base, + ChargeState: &decorateTronityChargeStateImpl{ + chargeState: chargeState, + }, + VehicleOdometer: &decorateTronityVehicleOdometerImpl{ + vehicleOdometer: vehicleOdometer, + }, + VehicleStartCharge: &decorateTronityVehicleStartChargeImpl{ + vehicleStartCharge: vehicleStartCharge, + }, + VehicleStopCharge: &decorateTronityVehicleStopChargeImpl{ + vehicleStopCharge: vehicleStopCharge, + }, + } + } + + return nil +} + +type decorateTronityChargeStateImpl struct { + chargeState func() (api.ChargeStatus, error) +} + +func (impl *decorateTronityChargeStateImpl) Status() (api.ChargeStatus, error) { + return impl.chargeState() +} + +type decorateTronityVehicleOdometerImpl struct { + vehicleOdometer func() (float64, error) +} + +func (impl *decorateTronityVehicleOdometerImpl) Odometer() (float64, error) { + return impl.vehicleOdometer() +} + +type decorateTronityVehicleStartChargeImpl struct { + vehicleStartCharge func() error +} + +func (impl *decorateTronityVehicleStartChargeImpl) StartCharge() error { + return impl.vehicleStartCharge() +} + +type decorateTronityVehicleStopChargeImpl struct { + vehicleStopCharge func() error +} + +func (impl *decorateTronityVehicleStopChargeImpl) StopCharge() error { + return impl.vehicleStopCharge() +}