Detect vehicle charge status only when connecting (#1165)
This commit is contained in:
parent
58d7acf498
commit
71ae0defff
1 changed files with 77 additions and 51 deletions
|
|
@ -103,11 +103,12 @@ type LoadPoint struct {
|
|||
chargeTimer api.ChargeTimer
|
||||
chargeRater api.ChargeRater
|
||||
|
||||
chargeMeter api.Meter // Charger usage meter
|
||||
vehicle api.Vehicle // Currently active vehicle
|
||||
vehicles []api.Vehicle // Assigned vehicles
|
||||
socEstimator *soc.Estimator
|
||||
socTimer *soc.Timer
|
||||
chargeMeter api.Meter // Charger usage meter
|
||||
vehicle api.Vehicle // Currently active vehicle
|
||||
vehicles []api.Vehicle // Assigned vehicles
|
||||
socEstimator *soc.Estimator
|
||||
socTimer *soc.Timer
|
||||
vehicleIdError error // state of last vehicle identification
|
||||
|
||||
// cached state
|
||||
status api.ChargeStatus // Charger status
|
||||
|
|
@ -327,6 +328,9 @@ func (lp *LoadPoint) evVehicleConnectHandler() {
|
|||
// flush all vehicles before updating state
|
||||
provider.ResetCached()
|
||||
|
||||
// identify active vehicle
|
||||
lp.findActiveVehicle()
|
||||
|
||||
// immediately allow pv mode activity
|
||||
lp.pvDisableTimer()
|
||||
|
||||
|
|
@ -424,6 +428,7 @@ func (lp *LoadPoint) Prepare(uiChan chan<- util.Param, pushChan chan<- push.Even
|
|||
// run during prepare() to ensure cache has been attached
|
||||
if len(lp.vehicles) > 0 {
|
||||
lp.setActiveVehicle(lp.vehicles[0])
|
||||
lp.findActiveVehicle()
|
||||
}
|
||||
|
||||
// read initial charger state to prevent immediately disabling charger
|
||||
|
|
@ -597,6 +602,9 @@ func (lp *LoadPoint) setActiveVehicle(vehicle api.Vehicle) {
|
|||
lp.log.INFO.Printf("vehicle updated: %s -> %s", lp.vehicle.Title(), vehicle.Title())
|
||||
}
|
||||
|
||||
// update successful
|
||||
lp.vehicleIdError = nil
|
||||
|
||||
lp.vehicle = vehicle
|
||||
lp.socEstimator = soc.NewEstimator(lp.log, vehicle, lp.SoC.Estimate)
|
||||
|
||||
|
|
@ -604,32 +612,39 @@ func (lp *LoadPoint) setActiveVehicle(vehicle api.Vehicle) {
|
|||
lp.publish("socCapacity", lp.vehicle.Capacity())
|
||||
}
|
||||
|
||||
// vehicleIdentificationAllowed returns true if active vehicle has not yet been identified
|
||||
func (lp *LoadPoint) vehicleIdentificationAllowed() bool {
|
||||
return errors.Is(lp.vehicleIdError, api.ErrMustRetry)
|
||||
}
|
||||
|
||||
// findActiveVehicle validates if the active vehicle is still connected to the loadpoint
|
||||
func (lp *LoadPoint) findActiveVehicle() {
|
||||
// find vehicles by id
|
||||
if identifier, ok := lp.charger.(api.Identifier); ok {
|
||||
id, err := identifier.Identify()
|
||||
|
||||
if err == nil {
|
||||
lp.log.DEBUG.Println("charger vehicle id:", id)
|
||||
|
||||
// find exact match
|
||||
for _, vehicle := range lp.vehicles {
|
||||
if vid, err := vehicle.Identify(); err == nil && vid == id {
|
||||
lp.setActiveVehicle(vehicle)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// find placeholder match
|
||||
for _, vehicle := range lp.vehicles {
|
||||
if vid, err := vehicle.Identify(); err == nil && vid == "*" {
|
||||
lp.setActiveVehicle(vehicle)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
lp.vehicleIdError = err
|
||||
lp.log.ERROR.Println("charger vehicle id:", err)
|
||||
return
|
||||
}
|
||||
|
||||
lp.log.DEBUG.Println("charger vehicle id:", id)
|
||||
|
||||
// find exact match
|
||||
for _, vehicle := range lp.vehicles {
|
||||
if vid, err := vehicle.Identify(); err == nil && vid == id {
|
||||
lp.setActiveVehicle(vehicle)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// find placeholder match
|
||||
for _, vehicle := range lp.vehicles {
|
||||
if vid, err := vehicle.Identify(); err == nil && vid == "*" {
|
||||
lp.setActiveVehicle(vehicle)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// TODO implement removing vehicle
|
||||
|
|
@ -640,39 +655,47 @@ func (lp *LoadPoint) findActiveVehicle() {
|
|||
return
|
||||
}
|
||||
|
||||
// find vehicles by charge state
|
||||
// find vehicles by charge state - current vehicle
|
||||
if vs, ok := lp.vehicle.(api.ChargeState); ok {
|
||||
status, err := vs.Status()
|
||||
|
||||
if err == nil {
|
||||
lp.log.DEBUG.Printf("vehicle status: %s (%s)", status, lp.vehicle.Title())
|
||||
if err != nil {
|
||||
lp.vehicleIdError = err
|
||||
lp.log.ERROR.Println("vehicle charge state:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// vehicle is plugged or charging, so it should be the right one
|
||||
if status == api.StatusB || status == api.StatusC {
|
||||
lp.log.DEBUG.Printf("vehicle status: %s (%s)", status, lp.vehicle.Title())
|
||||
|
||||
// vehicle is plugged or charging, so it should be the right one
|
||||
if status == api.StatusB || status == api.StatusC {
|
||||
lp.vehicleIdError = nil
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// find vehicles by charge state
|
||||
for _, vehicle := range lp.vehicles {
|
||||
if vehicle == lp.vehicle {
|
||||
continue
|
||||
}
|
||||
|
||||
if vs, ok := vehicle.(api.ChargeState); ok {
|
||||
status, err := vs.Status()
|
||||
|
||||
if err != nil {
|
||||
lp.vehicleIdError = err
|
||||
lp.log.ERROR.Println("vehicle charge state:", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, vehicle := range lp.vehicles {
|
||||
if vehicle == lp.vehicle {
|
||||
continue
|
||||
}
|
||||
lp.log.DEBUG.Printf("vehicle status: %s (%s)", status, vehicle.Title())
|
||||
|
||||
if vs, ok := vehicle.(api.ChargeState); ok {
|
||||
status, err := vs.Status()
|
||||
|
||||
if err == nil {
|
||||
lp.log.DEBUG.Printf("vehicle status: %s (%s)", status, vehicle.Title())
|
||||
|
||||
// vehicle is plugged or charging, so it should be the right one
|
||||
if status == api.StatusB || status == api.StatusC {
|
||||
lp.setActiveVehicle(vehicle)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
// vehicle is plugged or charging, so it should be the right one
|
||||
if status == api.StatusB || status == api.StatusC {
|
||||
lp.setActiveVehicle(vehicle)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
lp.log.ERROR.Println("vehicle charge state:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -983,10 +1006,13 @@ func (lp *LoadPoint) Update(sitePower float64) {
|
|||
lp.publish("charging", lp.charging())
|
||||
lp.publish("enabled", lp.enabled)
|
||||
|
||||
// update active vehicle and publish soc
|
||||
// must be run after updating charger status to make sure
|
||||
// update active vehicle if not yet done
|
||||
if lp.vehicleIdentificationAllowed() {
|
||||
lp.findActiveVehicle()
|
||||
}
|
||||
|
||||
// publish soc after updating charger status to make sure
|
||||
// initial update of connected state matches charger status
|
||||
lp.findActiveVehicle()
|
||||
lp.publishSoCAndRange()
|
||||
|
||||
// sync settings with charger
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue