Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/decorate/decorate.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func init() {
reflect.TypeFor[api.VehicleRange](),
reflect.TypeFor[api.VehicleClimater](),
reflect.TypeFor[api.VehicleFinishTimer](),
reflect.TypeFor[api.VehiclePosition](),
reflect.TypeFor[api.Identifier](),
reflect.TypeFor[api.ChargerEx](),
reflect.TypeFor[api.ChargeRater](),
Expand Down
11 changes: 11 additions & 0 deletions templates/definition/vehicle/homeassistant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ params:
en: Finish time (ISO8601 or Unix)
service: homeassistant/entities?uri={uri}&domain=sensor
example: "sensor.vehicle_finish_time"
- name: position
description:
de: Fahrzeugposition
en: Vehicle position
service: homeassistant/entities?uri={uri}&domain=device_tracker
example: "device_tracker.vehicle"
advanced: true
help:
en: Entity ID for vehicle position (`device_tracker` with `latitude`/`longitude` attributes, can be used for geofencing with the `vehicle-api` charger)
de: Entitäts-ID für Fahrzeugposition (`device_tracker` mit `latitude`/`longitude`-Attributen, kann für Geofencing mit dem `vehicle-api`-Charger verwendet werden)
- name: start_charging
description:
de: Service zum Laden starten
Expand Down Expand Up @@ -109,6 +119,7 @@ render: |
odometer: {{ .odometer }}
climater: {{ .climater }}
finishTime: {{ .finishTime }}
position: {{ .position }}
services:
start_charging: {{ .start_charging }}
stop_charging: {{ .stop_charging }}
Expand Down
14 changes: 12 additions & 2 deletions util/homeassistant/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,20 @@ func (c *Connection) GetBoolState(entity string) (bool, error) {
case "off", "false", "0", "inactive", "no":
return false, nil
default:
return false, fmt.Errorf("invalid boolean state '%s' for entity %s", state, entity)
return false, fmt.Errorf("invalid boolean state '%s' for entity %s", state.State, entity)
}
}

// GetPositionState retrieves latitude and longitude from a device_tracker entity's attributes
func (c *Connection) GetPositionState(entity string) (float64, float64, error) {
state, err := c.GetState(entity)
if err != nil {
return 0, 0, err
}

return state.Attributes.Latitude, state.Attributes.Longitude, nil
}

// GetTimeState retrieves the state of an entity as time
func (c *Connection) GetTimeState(entity string) (time.Time, error) {
state, err := c.GetState(entity)
Expand Down Expand Up @@ -208,7 +218,7 @@ func (c *Connection) GetChargeStatus(entity string) (api.ChargeStatus, error) {
return status, nil
}

return api.StatusNone, fmt.Errorf("unknown charge status: %s", state)
return api.StatusNone, fmt.Errorf("unknown charge status: %s", state.State)
}

// CallService calls a Home Assistant service
Expand Down
8 changes: 5 additions & 3 deletions util/homeassistant/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ type StateResponse struct {
EntityId string `json:"entity_id"`
State string `json:"state"`
Attributes struct {
UnitOfMeasurement string `json:"unit_of_measurement"`
DeviceClass string `json:"device_class"`
FriendlyName string `json:"friendly_name"`
UnitOfMeasurement string `json:"unit_of_measurement"`
DeviceClass string `json:"device_class"`
FriendlyName string `json:"friendly_name"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
} `json:"attributes"`
}

Expand Down
6 changes: 6 additions & 0 deletions vehicle/homeassistant.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func NewHomeAssistantVehicleFromConfig(other map[string]any) (api.Vehicle, error
Odometer string // optional
Climater string // optional
FinishTime string // optional
Position string // device_tracker.* optional
}
Services struct {
Start string `mapstructure:"start_charging"` // script.* optional
Expand Down Expand Up @@ -76,6 +77,7 @@ func NewHomeAssistantVehicleFromConfig(other map[string]any) (api.Vehicle, error
enable func(bool) error
wakeup func() error
maxcurrent func(int64) error
position func() (float64, float64, error)
)

if cc.Sensors.LimitSoc != "" {
Expand Down Expand Up @@ -111,6 +113,9 @@ func NewHomeAssistantVehicleFromConfig(other map[string]any) (api.Vehicle, error
if cc.Services.SetMaxCurrent != "" {
maxcurrent = func(current int64) error { return conn.CallNumberService(cc.Services.SetMaxCurrent, float64(current)) }
}
if cc.Sensors.Position != "" {
position = func() (float64, float64, error) { return conn.GetPositionState(cc.Sensors.Position) }
}

// decorate all features
return decorateVehicle(
Expand All @@ -125,6 +130,7 @@ func NewHomeAssistantVehicleFromConfig(other map[string]any) (api.Vehicle, error
finish,
wakeup,
enable,
position,
), nil
}

Expand Down
4 changes: 2 additions & 2 deletions vehicle/vehicle.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/evcc-io/evcc/util"
)

//go:generate go tool decorate -f decorateVehicle -b api.Vehicle -t api.SocLimiter,api.ChargeState,api.VehicleRange,api.VehicleOdometer,api.VehicleClimater,api.CurrentController,api.CurrentGetter,api.VehicleFinishTimer,api.Resurrector,api.ChargeController
//go:generate go tool decorate -f decorateVehicle -b api.Vehicle -t api.SocLimiter,api.ChargeState,api.VehicleRange,api.VehicleOdometer,api.VehicleClimater,api.CurrentController,api.CurrentGetter,api.VehicleFinishTimer,api.Resurrector,api.ChargeController,api.VehiclePosition

// Vehicle is an api.Vehicle implementation with configurable getters and setters.
type Vehicle struct {
Expand Down Expand Up @@ -149,7 +149,7 @@ func NewConfigurableFromConfig(ctx context.Context, other map[string]any) (api.V
return nil, errors.New("cannot have charge control without status")
}

return decorateVehicle(v, limitSoc, status, rng, odo, climater, maxCurrent, getMaxCurrent, finishTime, wakeup, chargeEnable), nil
return decorateVehicle(v, limitSoc, status, rng, odo, climater, maxCurrent, getMaxCurrent, finishTime, wakeup, chargeEnable, nil), nil
}

// Soc implements the api.Vehicle interface
Expand Down
Loading
Loading