Dynamically add/remove vehicles (#9903)

This commit is contained in:
andig 2023-09-17 11:37:17 +02:00 • committed by GitHub
parent abfefb7c01
commit dd668c3007
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 109 additions and 18 deletions

View file

@ -1,6 +1,8 @@
package coordinator
import (
"sync"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/core/loadpoint"
"github.com/evcc-io/evcc/util"
@ -8,6 +10,7 @@ import (
// Coordinator coordinates vehicle access between loadpoints
type Coordinator struct {
mu sync.Mutex
log *util.Logger
vehicles []api.Vehicle
tracked map[api.Vehicle]loadpoint.API
@ -24,10 +27,46 @@ func New(log *util.Logger, vehicles []api.Vehicle) *Coordinator {
// GetVehicles returns the list of all vehicles
func (c *Coordinator) GetVehicles() []api.Vehicle {
c.mu.Lock()
defer c.mu.Unlock()
return c.vehicles
}
func (c *Coordinator) Add(vehicle api.Vehicle) {
c.mu.Lock()
defer c.mu.Unlock()
c.vehicles = append(c.vehicles, vehicle)
}
func (c *Coordinator) Delete(vehicle api.Vehicle) {
c.mu.Lock()
for i, v := range c.vehicles {
if v == vehicle {
c.vehicles = append(c.vehicles[:i], c.vehicles[i+1:]...)
if o, ok := c.tracked[vehicle]; ok {
// defer call to SetVehicle to avoid deadlock on c.mu
defer func(o loadpoint.API) {
o.SetVehicle(nil)
}(o)
}
delete(c.tracked, vehicle)
break
}
}
// unlock before deferred SetVehicle executes a this will round-trip back here
c.mu.Unlock()
}
func (c *Coordinator) acquire(owner loadpoint.API, vehicle api.Vehicle) {
c.mu.Lock()
defer c.mu.Unlock()
if o, ok := c.tracked[vehicle]; ok && o != owner {
o.SetVehicle(nil)
}
@ -35,6 +74,9 @@ func (c *Coordinator) acquire(owner loadpoint.API, vehicle api.Vehicle) {
}
func (c *Coordinator) release(vehicle api.Vehicle) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.tracked, vehicle)
}
@ -43,6 +85,9 @@ func (c *Coordinator) release(vehicle api.Vehicle) {
func (c *Coordinator) availableDetectibleVehicles(owner loadpoint.API) []api.Vehicle {
var res []api.Vehicle
c.mu.Lock()
defer c.mu.Unlock()
for _, vv := range c.vehicles {
// status api available
if _, ok := vv.(api.ChargeState); ok {
@ -59,6 +104,10 @@ func (c *Coordinator) availableDetectibleVehicles(owner loadpoint.API) []api.Veh
// identifyVehicleByStatus finds active vehicle by charge state
func (c *Coordinator) identifyVehicleByStatus(available []api.Vehicle) api.Vehicle {
var res api.Vehicle
c.mu.Lock()
defer c.mu.Unlock()
for _, vehicle := range available {
if vs, ok := vehicle.(api.ChargeState); ok {
status, err := vs.Status()